GithubHelp home page GithubHelp logo

holgern / pyedflib Goto Github PK

View Code? Open in Web Editor NEW
210.0 12.0 121.0 1.89 MB

pyedflib is a python library to read/write EDF+/BDF+ files based on EDFlib.

Home Page: http://pyedflib.readthedocs.org/

License: BSD 3-Clause "New" or "Revised" License

Python 52.68% C 39.20% Batchfile 0.32% Shell 0.08% Cython 7.72%
bdf edf python edf-files

pyedflib's Introduction

pyEDFlib

Test Coverage Docs Build PyPI Version Conda Version Conda Downloads

pyEDFlib is a python library to read/write EDF+/BDF+ files based on EDFlib.

EDF means European Data Format and was firstly published Kemp1992. In 2003, an improved version of the file protocol named EDF+ has been published and can be found at Kemp2003.

The EDF/EDF+ format saves all data with 16 Bit. The company BioSemi introduced a version which saves all data with 24 Bit.

The definition of the EDF/EDF+/BDF/BDF+ format can be found under edfplus.info.

This Python toolbox is a fork of the toolbox from Christopher Lee-Messer and uses the EDFlib from Teunis van Beelen. The EDFlib is able to read and write EDF/EDF+/BDF/BDF+ files.

Documentation is available online at https://pyedflib.readthedocs.io.

pyEDFlib can be used with Python >=3.7. It depends on the Numpy package. To use the newest source code from git, you have to download the source code. You need a C compiler and a recent version of Cython. Go then to the source directory and type:

python setup.py build
python setup.py install

There are binary wheels which can be installed by (use pip3 when available):

pip install pyEDFlib

Users of the Anaconda Python distribution can directly obtain pre-built Windows, Intel Linux or macOS / OSX binaries from the conda-forge channel. This can be done via:

conda install -c conda-forge pyedflib

The most recent development version can be found on GitHub at https://github.com/holgern/pyedflib.

The latest release, including source and binary packages for Linux, macOS and Windows, is available for download from the Python Package Index. You can find source releases at the Releases Page.

pyEDFlib includes an highlevel interface for easy access to read and write edf files. Additionally functionality as anonymizing, dropping or renaming channels can be found there.

from pyedflib import highlevel

# write an edf file
signals = np.random.rand(5, 256*300)*200 # 5 minutes of random signal
channel_names = ['ch1', 'ch2', 'ch3', 'ch4', 'ch5']
signal_headers = highlevel.make_signal_headers(channel_names, sample_frequency=256)
header = highlevel.make_header(patientname='patient_x', gender='Female')
highlevel.write_edf('edf_file.edf', signals, signal_headers, header)

# read an edf file
signals, signal_headers, header = highlevel.read_edf('edf_file.edf', ch_names=['ch1', 'ch2'])
print(signal_headers[0]['sample_frequency']) # prints 256

# drop a channel from the file or anonymize edf
highlevel.drop_channels('edf_file.edf', to_drop=['ch2', 'ch4'])
highlevel.anonymize_edf('edf_file.edf', new_file='anonymized.edf'
                         to_remove=['patientname', 'birthdate'],
                         new_values=['anonymized', ''])
# check if the two files have the same content
highlevel.compare_edf('edf_file.edf', 'anonymized.edf')
# change polarity of certain channels
highlevel.change_polarity('file.edf', channels=[1,3])
# rename channels within a file
highlevel.rename_channels('file.edf', mapping={'C3-M1':'C3'})

pyEDFlib is a free Open Source software released under the BSD 2-clause license.

Releases can be cited via Zenodo.

pyedflib's People

Contributors

alistairewj avatar anthracene avatar bitterisland07 avatar blakejc94 avatar cboulay avatar cbrnr avatar cfranklin11 avatar cmiller01 avatar dimitripapadopoulos avatar dojeda avatar dthkao avatar emmanuel-ferdman avatar firefly-cpp avatar hofaflo avatar holgern avatar j9ac9k avatar jcbsv avatar jukka avatar lucacerina avatar mattbit avatar mensaah avatar musicinmybrain avatar myd7349 avatar raphaelvallat avatar sappelhoff avatar skjerns avatar wenh06 avatar wmvanvliet avatar ximion avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pyedflib's Issues

PR #44 seems to be causing test failures

Was PR #44 tested in Python 3? When I run test_edfwriter.py in py3 I see:

ValueError: Buffer dtype mismatch, expected 'int32_t' but got 'long'
This seems to stem from blockwrite_digital_samples in _pyedflib.pyx explicitly expecting int32, but np.int (equivalently the builtin int) in python has a version-dependent underlying dtype.

Does using np.int32 make more sense here?

Write EDF

Is it possible to write from Text file to EDF with this python library ?

Problem with setGender

Hi,
thanks for this helpful tool!

I'm trying to create a new edf-File from a excisting edf-file and I figured out, that the setGender('Male') command will return a female subject. And also setGender('Female') will produce a male subject.

Install via pip fails on Windows (no file stdio.h)

Hello,
I am trying to install pyedflib on windows but I get this error message :

C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Tools\MSVC\14.14.26428\bin\HostX86\x64\cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MD -DPY_EXTENSION -D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE -Ipyedflib\_extensions\c -Ic:\users\reynaud\appdata\local\programs\python\python37\include "-IC:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Tools\MSVC\14.14.26428\include" /Tcpyedflib\_extensions\c/edflib.c /Fobuild\temp.win-amd64-3.7\pyedflib\_extensions\c/edflib.obj
    edflib.c
    c:\users\reynaud\appdata\local\temp\pip-install-syove6p_\pyedflib\pyedflib\_extensions\c\edflib.h(42): fatal error C1083: Impossible d'ouvrir le fichier includeÿ: 'stdio.h'ÿ: No such file or directory
    error: command 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\BuildTools\\VC\\Tools\\MSVC\\14.14.26428\\bin\\HostX86\\x64\\cl.exe' failed with exit status 2
    ----------------------------------------
ERROR: Command errored out with exit status 1: 'c:\users\reynaud\appdata\local\programs\python\python37\python.exe' -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'C:\\Users\\reynaud\\AppData\\Local\\Temp\\pip-install-syove6p_\\pyedflib\\setup.py'"'"'; __file__='"'"'C:\\Users\\reynaud\\AppData\\Local\\Temp\\pip-install-syove6p_\\pyedflib\\setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record 'C:\Users\reynaud\AppData\Local\Temp\pip-record-xr1jncb7\install-record.txt' --single-version-externally-managed --compile Check the logs for full command output.

Can anyone help ?
thanks !!
Robin

Wrong and misleading docstring for setDatarecordDuration

Hey,

Just wanted to point out that the documentation for EdfWriter.setDatarecordDuration is wrong and a bit misleading.

Looking at the corresponding function edf_set_datarecord_duration in edflib.c it is clear that the duration should be in the range 0.001 to 60 seconds, not 0.05 to 20.0 seconds. This is also documented in edflib.h.

Also, it could be good to point out that the unit of the duration is in 10 microseconds. Now you get the picture that the unit is 1 seconds. This caused me some grey hairs as I tried to set a non-integer sample rate 😄

Appreciate your work on the library!

Add feature to split EDF+D file in EDF+C

Currently pyedflib does not allow to load or manipulate EDF+D (discontinuous) files.

Would it be possible to add a function to split an EDF+D file in EDF+C part files?
This way users of the pyedflib library could split the files from pyedflib before loading each individual part.

Incorrect results from calling read_digital_signal when opening more than one file

Calling read_digital_signal from the first EdfReader instance is alright. However, if calling it from the following instances, it will return incorrect results. After looking at the _pyedflib.pyx, self.handle causes the problem. It has never been assigned to any value but is used in read_digital_signal. If I added

def check_open_ok(self, result):
if result == 0:
self.handle = self.hdr.handle <---- add this line
return True
else:
raise IOError, open_errors[self.hdr.filetype]

, everything seems to work correctly. I don't know why the code still needs self.handle. If removing "cdef int handle" and change self.handle to self.hdr.handle, I think _pyedflib.pyx should work as expected. Haven't tested though.

Pre-build wheels for latest version

Hi @holgern
Thanks for the great package.
Is there any chance you could upload the linux wheels to pypi for the lastest version, please? We are trying to get this setup on a barebones docker image, and would rather not install gcc.
Thanks!

How to close an already opened file?

Hi,

I'm trying to read EEG signals and I'm quite new to this field. I ran the following script.

f = pyedflib.EdfReader("chb01_01.edf")
print(f)
n = f.signals_in_file
print("number of signals in file:", n)
signal_labels = f.getSignalLabels()
print("signal_labels:", signal_labels)

It worked fine when I ran it for the first time. However, if I run it again, I get the following error:

IOError: file has already been opened

I have tried inserting 1. f._close() 2. f._close() followed by del f, after the print("signal_labels..... ) function but failed. Is there a way to fix this error? Thanks a lot

DOC

The first MWE present in the doc does not work 'cos the file is not present if you copy paste.

>>> import pyedflib
>>> import numpy as np
>>> f = pyedflib.EdfReader("data/test_generator.edf")
>>> n = f.signals_in_file
>>> signal_labels = f.getSignalLabels()
>>> sigbufs = np.zeros((n, f.getNSamples()[0]))
>>> for i in np.arange(n):
>>>     sigbufs[i, :] = f.readSignal(i)

consider doing something like:

import pyedflib
import numpy as np
import os

file_name = os.path.join(pyedflib.util.test_data_path(),
                         'test_generator.edf')
f = pyedflib.EdfReader(file_name)
n = f.signals_in_file
signal_labels = f.getSignalLabels()
sigbufs = np.zeros((n, f.getNSamples()[0]))
for i in np.arange(n):
    sigbufs[i, :] = f.readSignal(i)

Cannot open file containing accented character on Windows

Hi,

First, thanks for this great library! :)

If I try to open a file containing an accented character on it's name, on Windows (like "á"), I get an error (see below). If the accented character is removed from the file name, the file opens normally.

Stack trace:

OSError                                   Traceback (most recent call last)
    126 
--> 127     with pyedflib.EdfReader(filename) as f:
    128         print(f.signals_in_file)
    129 

pyedflib\_extensions\_pyedflib.pyx in pyedflib._extensions._pyedflib.CyEdfReader.__init__()

pyedflib\_extensions\_pyedflib.pyx in pyedflib._extensions._pyedflib.CyEdfReader.open()

pyedflib\_extensions\_pyedflib.pyx in pyedflib._extensions._pyedflib.CyEdfReader.check_open_ok()

OSError: can not open file, no such file or directory

Streaming mode

Hi,

First of all, great work. I am relatively new to working with EDF files and Python, but this library has made my work so much easier.

The "EDFBrowser" software (downloaded from https://www.teuniz.net/edfbrowser/index.html) from has a streaming mode, which can be used to read a growing EDF file and display graphs (for e.g. ECG, EMG, Respiration etc.).

When i try to do read a streaming file with pyedflib.EDFreader, I get this error:

"the file is not EDF(+) or BDF(+) compliant (Number of Data Records)".

Is there a workaround/solution for reading such files with pyedflib?

Appreciate any help.

Thanks

CHB-MIT (Physionet) error - regular EDF not supported anymore

Hi,

So I was having an issue reading some edf files from the CHB-MIT database. This issue was reported here. I, therefore, followed your recent advice to update the pyedflib version.
However, I found myself with another error:

OSError: the file is not EDF(+) or BDF(+) compliant (it contains format errors)

So I looked a bit into it and here is what's happening:
in some CHB-MIT edf files (chb12_06 for example), the header contains some blacked out channels (i.e. their label is "-"). These channels have their digital maximum equal to their digital minimum. This is problematic for pyedflib who considers that there is a format error (that's what I understand from my poor reading of C code).
This was also confirmed when I tried to open them in EDFBrowser:

Error, digital maximum of signal 5 is less than or equal to digital minimum
 File is not a valid EDF or BDF file.

I wanted to know why you had this check. What I mean is, I don't think it's really that bad if the maximum is equal to the minimum (maybe just issue a warning when they are equal) and I don't see it in the EDF specs.

I also wanted to know if others had had this issue and how they coped with it.

Don't hesitate to ask for additional details and thanks in advance for your help.

EDIT: The channels which caused the issue were not blacked out, an explanation is actually given here :

In some cases, up to 5 “dummy” signals (named "-") were interspersed among the EEG signals to obtain an easy-to-read display format; these dummy signals can be ignored.

Error with chb17b_69 in CHB-MIT (Physionet) Database

Hi,

So I was having this issue on a lot of files from the CHB-MIT db. Fortunately, @holgern managed to solve it. I downloaded the new version and went on with my life.

However, I hadn't noticed the error on chb17b_69 since I was focusing only on files with associated seizures:

OSError: the file is not EDF(+) or BDF(+) compliant (it contains format errors)

Unlike last time, I have no clue concerning the origin of the problem for two reasons:

  • EDFBrowser hasn't solved the problem mentioned here; I will immediately write an issue about that. However, at the moment it's impossible for me to have additional details on why the format is bad.
  • The errors in pyedflib are not very helpful in order to identify the origin of the bad formatting. I wonder if it's possible to enhance the errors in order to allow for "debugging".

I also compared with the file just before (chb17b_68) and the headers are the same, so it's not in that part.

Don't hesitate to ask for additional details and thanks in advance for your help.

A gentle favor and a weird issue.

Hey, thanks for this brilliant repo;

I'm analyzing the EEG data for 'sleep stage scoring';

Favor

  1. How can I cut one channel of .edf file into 30s-epoch data group?

  2. How can I mark the annotations to each 30s-epoch, or labeling the 'W, N1, N2, N3, R' labels to every 30s-epoch data?

Data structure

  1. .edf : each one obtains 10 (or more) channels info.

  2. .csv:

No. StartTime Label
1 21:34:57 WK
2 21:35:27 WK
3 21:35:57 WK
4 21:36:27 WK
5 21:36:57 WK
6 21:37:27 WK
7 21:37:57 WK
... ... ...

Ideal result

30s-epoch(1x(30*Fs))


30s-epoch : WK
... : ..
30s-epoch : N2

End

  1. Different one: WHERE I CAN FIND API INFO?

Because : I wanna get the end time of a edf signal, so : `f.getEnddatetime().',

EdfReader' object has no attribute 'getEnddatetime'`

Thus where I can find the correct attribute for EdfReader(OR OTHER ONE ) ?
Please do not hesitate to let me know if you have any questions.
It is greatly grateful if it would be responded;

AttributeError: 'str' object has no attribute 'shape' thrown by writeSamples

exception:
Traceback (most recent call last):
File "accellog.py", line 99, in
main(sys.argv[1:])
File "accellog.py", line 78, in main
f.writeSamples(data_list)
File "/usr/local/lib/python2.7/dist-packages/pyedflib/edfwriter.py", line 661, in writeSamples
lastSampleInd = int(np.max(data_list[i].shape) - ind[i])
AttributeError: 'str' object has no attribute 'shape'

accellog.py.zip

Incorrect header leads to modified signal

I noticed that when reading a signal with EdfReader, and writing it back out with all the fields the same (all headers, all signals, are unchanged) using EdfWriter, some channels might have its output "clipped"; this seems to happen when the digital values in the signal exceed the range of the digital max/min header for that signal. This is something that, in my opinion, should not be happening, as the output file should be written exactly as the input file (identity mapping).

One thing to mention here is that edf files from research labs, physionet, and other sources sometimes have incorrect digital max/min header values, but the data is still of value to researchers, who would like to use the "unclipped" data, either for validation of findings or for original research.

It seems as the following code section is the culprit, from quick inspection.

if(value>digmax)
{
  value = digmax;
}

if(value<digmin)
{
  value = digmin;
}

This is found in edflib.c, at lines
4001-4009,
4125-4133,
4255-4263,
4386-4394,
4617-4625,
4772-4780

setup.py fails on conda based python 3.7

When attempted to install via pip on a python 3.7 environment (on macOS) pip installation fails.

Installation via pip worked on a python 3.6 on the same system.

pip install pyedflib
Collecting pyedflib
  Using cached https://files.pythonhosted.org/packages/67/63/d00cfa8d3fb6bc374d19b083c963e30a34b4bc333a13d7d29543b89b8779/pyEDFlib-0.1.12.tar.gz
Requirement already satisfied: numpy>=1.9.1 in /usr/local/miniconda3/envs/test37/lib/python3.7/site-packages (from pyedflib) (1.14.5)
Building wheels for collected packages: pyedflib
  Running setup.py bdist_wheel for pyedflib ... error
  Complete output from command /usr/local/miniconda3/envs/test37/bin/python -u -c "import setuptools, tokenize;__file__='/private/var/folders/15/zd0gyh1n2tv9gl68lcvklz4c0000gn/T/pip-install-xg088jo7/pyedflib/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" bdist_wheel -d /private/var/folders/15/zd0gyh1n2tv9gl68lcvklz4c0000gn/T/pip-wheel-89tg3gzk --python-tag cp37:
  running bdist_wheel
  running build
  running build_py
  creating build
  creating build/lib.macosx-10.7-x86_64-3.7
  creating build/lib.macosx-10.7-x86_64-3.7/pyedflib
  copying pyedflib/version.py -> build/lib.macosx-10.7-x86_64-3.7/pyedflib
  copying pyedflib/__init__.py -> build/lib.macosx-10.7-x86_64-3.7/pyedflib
  copying pyedflib/edfreader.py -> build/lib.macosx-10.7-x86_64-3.7/pyedflib
  copying pyedflib/edfwriter.py -> build/lib.macosx-10.7-x86_64-3.7/pyedflib
  creating build/lib.macosx-10.7-x86_64-3.7/pyedflib/_extensions
  copying pyedflib/_extensions/__init__.py -> build/lib.macosx-10.7-x86_64-3.7/pyedflib/_extensions
  creating build/lib.macosx-10.7-x86_64-3.7/pyedflib/data
  copying pyedflib/data/_readers.py -> build/lib.macosx-10.7-x86_64-3.7/pyedflib/data
  copying pyedflib/data/__init__.py -> build/lib.macosx-10.7-x86_64-3.7/pyedflib/data
  copying pyedflib/data/test_generator.edf -> build/lib.macosx-10.7-x86_64-3.7/pyedflib/data
  running build_clib
  building 'c_edf' library
  creating build/temp.macosx-10.7-x86_64-3.7
  creating build/temp.macosx-10.7-x86_64-3.7/pyedflib
  creating build/temp.macosx-10.7-x86_64-3.7/pyedflib/_extensions
  creating build/temp.macosx-10.7-x86_64-3.7/pyedflib/_extensions/c
  gcc -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -I/usr/local/miniconda3/envs/test37/include -arch x86_64 -I/usr/local/miniconda3/envs/test37/include -arch x86_64 -DPY_EXTENSION -D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE -Ipyedflib/_extensions/c -I/usr/local/miniconda3/envs/test37/include/python3.7m -c pyedflib/_extensions/c/edflib.c -o build/temp.macosx-10.7-x86_64-3.7/pyedflib/_extensions/c/edflib.o
  pyedflib/_extensions/c/edflib.c:2605:44: warning: format specifies type 'int' but the argument has type 'off_t' (aka 'long long') [-Wformat]
           printf("filesize %d != %d*%d+%d ",ftello(inputfile),edfhdr->recordsize, edfhdr->datarecords, edfhdr->hdrsize);
                            ~~               ^~~~~~~~~~~~~~~~~
                            %lld
  pyedflib/_extensions/c/edflib.c:2605:82: warning: format specifies type 'int' but the argument has type 'long long' [-Wformat]
           printf("filesize %d != %d*%d+%d ",ftello(inputfile),edfhdr->recordsize, edfhdr->datarecords, edfhdr->hdrsize);
                                     ~~                                            ^~~~~~~~~~~~~~~~~~~
                                     %lld
  2 warnings generated.
  ar rc build/temp.macosx-10.7-x86_64-3.7/libc_edf.a build/temp.macosx-10.7-x86_64-3.7/pyedflib/_extensions/c/edflib.o
  ranlib build/temp.macosx-10.7-x86_64-3.7/libc_edf.a
  running build_ext
  building 'pyedflib._extensions._pyedflib' extension
  gcc -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -I/usr/local/miniconda3/envs/test37/include -arch x86_64 -I/usr/local/miniconda3/envs/test37/include -arch x86_64 -DPY_EXTENSION -D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE -Ipyedflib/_extensions/c -I/usr/local/miniconda3/envs/test37/lib/python3.7/site-packages/numpy/core/include -I/usr/local/miniconda3/envs/test37/include/python3.7m -c pyedflib/_extensions/_pyedflib.c -o build/temp.macosx-10.7-x86_64-3.7/pyedflib/_extensions/_pyedflib.o
  In file included from pyedflib/_extensions/_pyedflib.c:529:
  In file included from /usr/local/miniconda3/envs/test37/lib/python3.7/site-packages/numpy/core/include/numpy/arrayobject.h:4:
  In file included from /usr/local/miniconda3/envs/test37/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:18:
  In file included from /usr/local/miniconda3/envs/test37/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1816:
  /usr/local/miniconda3/envs/test37/lib/python3.7/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:15:2: warning: "Using deprecated NumPy API, disable it by "          "#defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION" [-W#warnings]
  #warning "Using deprecated NumPy API, disable it by " \
   ^
  pyedflib/_extensions/_pyedflib.c:32792:21: error: no member named 'exc_type' in 'struct _ts'
      *type = tstate->exc_type;
              ~~~~~~  ^
  pyedflib/_extensions/_pyedflib.c:32793:22: error: no member named 'exc_value' in 'struct _ts'; did you mean 'curexc_value'?
      *value = tstate->exc_value;
                       ^~~~~~~~~
                       curexc_value
...
    pyedflib/_extensions/_pyedflib.c:33106:13: error: no member named 'exc_type' in 'struct _ts'
        tstate->exc_type = *type;
        ~~~~~~  ^
    fatal error: too many errors emitted, stopping now [-ferror-limit=]
    1 warning and 20 errors generated.
    error: command 'gcc' failed with exit status 1

    ----------------------------------------
Command "/usr/local/miniconda3/envs/test37/bin/python -u -c "import setuptools, tokenize;__file__='/private/var/folders/15/zd0gyh1n2tv9gl68lcvklz4c0000gn/T/pip-install-xg088jo7/pyedflib/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /private/var/folders/15/zd0gyh1n2tv9gl68lcvklz4c0000gn/T/pip-record-sfmmj4il/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /private/var/folders/15/zd0gyh1n2tv9gl68lcvklz4c0000gn/T/pip-install-xg088jo7/pyedflib/

readSignal error: read -1, less than 921600 requested!!!

when I read chbmit01_03.edf file,
` f = pyedflib.EdfReader(fname)
nSignals = f.signals_in_file
nSamples = f.getNSamples()[0] #it is 921600
signal_labels = f.getSignalLabels()
freq = f.getSampleFrequency(0)
t = np.arange(nSamples, dtype=float)/60.0/freq
eeg = np.zeros((nSignals, f.getNSamples()[0]))

    for i in range(nSignals):
        print(f.readSignal(i).shape)
        eeg[i, :] = f.readSignal(i)`

I cann't read the data into eeg, it shows "read -1, less than 921600 requested!!!", how to deal with it? Thank you very much!!

Cannot open source file: 'pyedflib\src\_pyedflib.c': No such file or directory

This seems to have been introduced after release 0.1.4, when compiling in Windows:

running build_ext
building 'pyedflib._pyedflib' extension
C:\Users\Jacob\AppData\Local\Programs\Common\Microsoft\Visual C++ for Python\9.0\VC\Bin\cl.exe /c /nologo /Ox /MD /W3 /GS- /DNDEBUG -DPY_EXTENSION -Ipyedflib\src\c 
   -IC:\Users\Jacob\Anaconda2\envs\sleep_classifier\lib\site-packages\numpy\core\include 
   -IC:\Users\Jacob\Anaconda2\envs\sleep_classifier\include 
   -IC:\Users\Jacob\Anaconda2\envs\sleep_classifier\PC /Tcpyedflib\src\_pyedflib.c /Fobuild\temp.win32-2.7\Release\pyedflib\src\_pyedflib.obj _pyedflib.c
c1 : fatal error C1083: Cannot open source file: 'pyedflib\src\_pyedflib.c': No such file or directory

error: command 'C:\\Users\\Jacob\\AppData\\Local\\Programs\\Common\\Microsoft\\Visual C++ for Python\\9.0\\VC\\Bin\\cl.exe' failed with exit status 2

edf writer code executing really slow

Hi,

I am trying to create a edf file combining the small chunks of signals from the original edf file. There are 129 signals each with 2 hours long of data and each having sample frequency of 2000Hz. I have been trying to combine all 129 signals for last couple of days but I am not able to complete the process even when running the machine for 8 hours. However, I am able to combine upto 18 signals and even then it takes really long time.

I used the demo code for edfwriter and modified based on my need using a loop to add signals to data_list.

Could you let me know how I could write edf file faster?

Thank you

set_number_of_annotation_signals method needed

Currently limited to only 1 annotation 'channel'.

It wasn't entirely clear, but the edflib header suggests that there can only be one annotation per data record. If we have many annotations then we need more than that. Please correct me if I'm wrong.

WriteAnnotation fails on linux

Hello everyone,

There's a problem when writing annotation on Linux.
This error doesn't occur on Windows for the same code.
Following is a block of code that causes exception:

number_of_channels = len(data)
writer = pyedflib.EdfWriter(filename, number_of_channels, file_type=pyedflib.FILETYPE_EDFPLUS)
...
for note in annotations:
	logging.info("Writing %s, %f, %f",note[0],note[1],note[3])
	writer.writeAnnotation("test",1,-1)

Following is back-trace of the exception:

Traceback (most recent call last):
  File "builder.py", line 58, in <module>
    main()
...
    create_edf_file(path, data, sample_rate, annotations, labels)
  File "builder/edfbuilder.py", line 49, in create_edf_file
    writer.writeAnnotation("test",1,-1)
  File "builder/pyedflib/edfwriter.py", line 734, in writeAnnotation
    return write_annotation_utf8(self.handle, np.round(onset_in_seconds*10000).astype(int), np.round(duration_in_seconds*10000).astype(int), du(description))
  File "<__array_function__ internals>", line 6, in round_
  File "builder/numpy/core/fromnumeric.py", line 3599, in round_
    return around(a, decimals=decimals, out=out)
  File "<__array_function__ internals>", line 6, in around
  File "builder/numpy/core/fromnumeric.py", line 3224, in around
    return _wrapfunc(a, 'round', decimals=decimals, out=out)
  File "builder/numpy/core/fromnumeric.py", line 58, in _wrapfunc
    return _wrapit(obj, method, *args, **kwds)
  File "builder/numpy/core/fromnumeric.py", line 47, in _wrapit
    result = getattr(asarray(obj), method)(*args, **kwds)
TypeError: ufunc 'rint' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''

More information about the environment:

OS: Ubuntu 16.04.6 LTS
Linux: 4.15.0-72-generic
numpy==1.18.1
python: Python 3.7.6

Thanks in advance.

Corrupted file and clipped signals with signals of different lengths

If signals of different lengths are written to an EDF file, the signals read as if they had been clipped from the end to match the length of the shortest signal. Also, the file header appears to be corrupted when using another EDF reader (EDFbrowser). The error message from EDFbrowser reads:

Error, filesize does not match with the calculated filesize based on the parameters
in the header. Filesize is 2124 and filesize according to header is 2120.
You can fix this problem with the header editor, check the manual for details.
File is not a valid EDF or BDF file.

This would suggest that the missing data might actually be saved, but pyedflib does not read it. The scenario can be reproduced with the following code:

import pyedflib
import numpy as np

f = pyedflib.EdfWriter("test_different_lengths.edf", 3)
labels = ["1", "2", "3"]
derived_signals = [np.array(list(range(10))),
				   np.array(list(range(7))),
				   np.array(list(range(10)))]
headers = []
for label in labels:
	header = {'label': label, 'dimension': '', 'sample_rate': 1,
			  'physical_max': 10, 'physical_min': 0,
			  'digital_max': np.iinfo(np.int16).max, 'digital_min': np.iinfo(np.int16).min,
			  'transducer': '', 'prefilter':''}
	headers.append(header)
f.setSignalHeaders(headers)
f.writeSamples(derived_signals)
f.close()

edf_file = pyedflib.EdfReader("test_different_lengths.edf")
edf_samples = edf_file.getNSamples()
print(edf_samples) # [7 7 7]
# All of the following give approx. [0 1 2 3 4 5 6]
print(edf_file.readSignal(0)) # should be 10 long
print(edf_file.readSignal(1)) # should be 7 long - ok
print(edf_file.readSignal(2)) # should be 10 long

Re-writing EDF file changes signal data and signal header values

I'm reading an EDF file with EdfReader and I received the following signal headers and data values (excerpt):
...
"physical_max": 5859.19,
"physical_min": -5859.3,
"digital_max": 32767,
"digital_min": -32768,
...
... , 926.99941985, 875.32255085, 830.26175158, ...

The min and max values in the data were
5859.19
-5859.300000000001

I re-wrote the file using EdfWriter and when reading the result I received the following signal headers and data values:
...
"physical_max": 5859.189,
"physical_min": -5859.3,
"digital_max": 32767,
"digital_min": -32768,
...
... ,926.99884074, 875.32197615, 830.26118073, ...

The min and max values were
5859.189
-5859.300000000002

Why does EdfWriter shift the values down? Also, why is the physical_min value exceeded?

The scaling offset computed via the max values (e.g. here https://github.com/holgern/pyedflib/blob/master/pyedflib/_extensions/c/edflib.c#L4911) does not correspond to the EDF software guidelines: the scaling should be done via minimum values, as in "the formula to compute the physical value, P, from the digitally stored (16-bit integer) value, D, reads: P = Pmin + (Pmax - Pmin) * (D - Dmin) / (Dmax - Dmin)" (see https://www.edfplus.info/specs/guidelines.html). Could this be the source of this error?

Handling of wrong paths

Currently the library does not handle gracefully when a wrong file path is passed to pyedflib.EdfReader() since it raises a generic 'malloc error' (see trace below):

Traceback (most recent call last):
f = pyedflib.EdfReader(data_EDF)
File "pyedflib_extensions_pyedflib.pyx", line 91, in pyedflib._extensions._pyedflib.CyEdfReader.init (pyedflib_extensions_pyedflib.c:2674)
File "pyedflib_extensions_pyedflib.pyx", line 125, in pyedflib._extensions._pyedflib.CyEdfReader.open (pyedflib_extensions_pyedflib.c:3287)
File "pyedflib_extensions_pyedflib.pyx", line 101, in pyedflib._extensions._pyedflib.CyEdfReader.check_open_ok (pyedflib_extensions_pyedflib.c:2846)
IOError: malloc error

Write EDF files that are not an integer number of seconds long

I have a file with a sample rate of 200Hz. The length of the data is not an integer multiple of 200, for example let's say the signal is 1.5s (300 samples) long. Apparently, EdfWriter.writePhysicalSamples always writes blocks of 1s (which in my example is 200 samples). This results in a file which is 2s long, the last 0.5s of the data are filled with zeros.

Is it possible to write files that are not exactly an integer number of seconds long?

Double rounding when writing to file leads to accumulating errors

After a read-write-read cycle of an EDF file the sampel values get changed by a significant margin.
Digging up the responsible lines in the code (4604 and 4606 in _extensions/c/edflib.c -> edfwrite_physical_samples()) suggest that the two subsequent roundings might be the cause.
As a proof I included a simple code that compares the present implementation with the suggested (correct) one.

`#include <stdio.h>

int f1(double x, double p, double P, int d, int D) {
/*
converting double to int
implementation according to edflib.c
*/
int value;
double bitvalue, offset;
bitvalue = (P - p)/(D - d);
offset = P/bitvalue - D;
value = x/bitvalue; // rounding 1
value -= offset; // rounding 2
return value;
}

int f2(double x, double p, double P, int d, int D) {
/*
converting double to int
corrected implementation
*/
int value;
double bitvalue, offset;
bitvalue = (P - p)/(D - d);
offset = P/bitvalue - D;
value = x/bitvalue - offset; // rounding
return value;
}

double inv(int v, double p, double P, int d, int D) {
/*
converting int to double
implementation according to edflib.c
/
double bufvalue;
double bitvalue, offset;
bitvalue = (P - p)/(D - d);
offset = P/bitvalue - D;
bufvalue = bitvalue
(offset + v);
return bufvalue;
}

int main() {
int D = 2047; // dig_max
int d = -2048; // dim_min
double P = 249; // phys_max
double p = -251; // phys_min
double x1, x2; // signal values
int v1, v2; // stored values

    printf("Show that the two double->int conversions are not equivalent\n"$
    for(x1 = -1; x1 < 1; x1 += 0.13) {
            printf("x: %5f\t", x1);
            printf("f1: %d ", f1(x1, p, P, d, D));
            printf("f2: %d\n", f2(x1, p, P, d, D));
    }

    printf("Show that the edflib.c implementation (with two roundings)\n");
    printf("can lead to the accumulation of errors upon subsequent\n");
    printf("back and forth conversions\n");
    x1 = x2 = 0.3;
    for (int i = 0; i < 10; i++) {
            v1 = f1(x1, p, P, d, D); //  double->int the wrong way
            x1 = inv(v1, p, P, d, D);//  int->double
            v2 = f2(x2, p, P, d, D); //  double->int the right way
            x2 = inv(v2, p, P, d, D);//  int->double
            printf("x1: %4f\tv1: %d\t x2: %4f\tv2: %d\n", x1, v1, x2, v2); $
    }
    return 0;

}

`

Writer as context manager

Great work, first of all!

I wanted to use the EDFWriter as a context manager

with pyedflib.EdfWriter(edf_path, 13, file_type=pyedflib.FILETYPE_EDFPLUS) as f:
    pass

However, this did not have the expected effect of closing the file after the context was left.
When running the same context again, it will tell me

OSError: file has already been opened

I could not find the fault, as you correctly implemented the __enter__/__exit__ methods. Do you know anything about it?

Module doesn't work with http://www.physionet.org/pn4/eegmmidb/ dataset

Hi,
I have a problem using pyedflib on OS X el capitan with Anaconda 2.7. When I'm trying to open one of the subjects EDF+ file, there's this traceback:

---------------------------------------------------------------------------
IOError                                   Traceback (most recent call last)
<ipython-input-2-8e83f56057db> in <module>()
----> 1 f = edf.EdfReader("S001R01.edf")

_pyedflib.pyx in _pyedflib.CyEdfReader.__init__ (pyedflib/src/_pyedflib.c:2497)()

_pyedflib.pyx in _pyedflib.CyEdfReader.open (pyedflib/src/_pyedflib.c:3122)()

_pyedflib.pyx in _pyedflib.CyEdfReader.check_open_ok (pyedflib/src/_pyedflib.c:2672)()

IOError: malloc error

Not sure if it's related to EDFLib, pyedflib or to the dataset itself.

writing digital sample data is not available.

Updating comment. I have successfully added the write_digital_signal code but found out that we are not handling errors from the c library.
I don't get an error when I write a signal header with matching physicalmin and max values. The file is created, the file handle is never released and no error is raised.
I'm going to do a pull request in the next day for my changes for write digital and may make time to look into error/exception handling after that.
Thanks for the library!

Total number of annotations cannot be higher than the file duration in seconds

Hi,
It seems that the maximum number of annotations that can be written in a EDF+ file with this library is equal to the duration in seconds of the signals. Why?
I have done several tests and for files with 10s, 100s, 1000s or 10000s long records it's not possible to write more than 10, 100, 1000 or 10000 annotations respectively. There is no error raised by the f.writeAnnotation method, I just found it out after opening the newly created file where only the first N=records_duration annotations where present. I don't know if this is a limit of the EDF format but if so, it should be documented and the f.writeAnnotation method should return an error code if a limit is reached.
Best,
Jose

reading directly from online data archive

It would be great for saving disk space if you could import data directly from an online archive, rather than referencing a local storage location.

e.g.

pyedflib.EdfReader("https://www.physionet.org/pn6/chbmit/chb01/chb01_01.edf")

perhaps there is already a way to do this?

Here is the current error message from trying above:

pyedflib/_extensions/_pyedflib.pyx in pyedflib._extensions._pyedflib.CyEdfReader.__init__()

pyedflib/_extensions/_pyedflib.pyx in pyedflib._extensions._pyedflib.CyEdfReader.open()

pyedflib/_extensions/_pyedflib.pyx in pyedflib._extensions._pyedflib.CyEdfReader.check_open_ok()

IOError: can not open file, no such file or directory

Ignoring OSError: the file is not EDF(+) or BDF(+) compliant (starttime)

I have a bunch of EDFs that I need to process as part of a Python data pipeline, but I am running into some problems with a large portion of them. The error comes from the fact that start time in some of the files have been processed wrongly before, so that the 'seconds' variable is more than 60 seconds in value.

I tried modifying the check_open_ok function in _pyedflib.pyx to

def check_open_ok(self,result):
    if result == 0:
        return True
    elif self.hdr.filetype in ['EDFLIB_FILE_ERRORS_STARTDATE', 'EDFLIB_FILE_ERRORS_STARTTIME']:
        return True
    else:
        raise IOError, open_errors[self.hdr.filetype]
        # return False

and then building again, but I still get the same error:

File "pyedflib/_extensions/_pyedflib.pyx", line 116, in pyedflib._extensions._pyedflib.CyEdfReader.__init__
  File "pyedflib/_extensions/_pyedflib.pyx", line 157, in pyedflib._extensions._pyedflib.CyEdfReader.open
  File "pyedflib/_extensions/_pyedflib.pyx", line 129, in pyedflib._extensions._pyedflib.CyEdfReader.check_open_ok
OSError: the file is not EDF(+) or BDF(+) compliant (starttime)

Would you know of any other way to skip this specific check, or am I perhaps not implementing the changes correctly (ie. building incorrectly? I am not an expert in modifying Python packages).

Issues reading EDF's

When I am trying to use the code on NSSR dataset, I am getting the following error message:
ValueError: could not broadcast input array from shape (3483750) into shape (27870)
when running
sigbufs[i, :] = f.readSignal(i)

IOError: malloc error

Code:
import pyedflib
import numpy as np
f = pyedflib.EdfReader("example.edf")
n = f.signals_in_file
signal_labels = f.getSignalLabels()
sigbufs = np.zeros((n,f.getNSamples()[0]))
for i in np.arange(n):
sigbufs[i,:] = f.readSignal(i)
print sigbufs

####################

Error:

/usr/bin/python2.7 "/media/tauqs/main_partition/Tauqueer/Academics/8th Sem/BTP/Preprocessing.py"
Traceback (most recent call last):
File "/media/tauqs/main_partition/Tauqueer/Academics/8th Sem/BTP/Preprocessing.py", line 3, in
f = pyedflib.EdfReader("example.edf")
File "_pyedflib.pyx", line 91, in pyedflib._extensions._pyedflib.CyEdfReader.init (pyedflib/_extensions/_pyedflib.c:2519)
File "_pyedflib.pyx", line 125, in pyedflib._extensions._pyedflib.CyEdfReader.open (pyedflib/_extensions/_pyedflib.c:3076)
File "_pyedflib.pyx", line 101, in pyedflib._extensions._pyedflib.CyEdfReader.check_open_ok (pyedflib/_extensions/_pyedflib.c:2679)
IOError: malloc error

Process finished with exit code 1

access subset of data

Just starting to work with EDF files for EEG. I have some very large EDF files (10 Gb) and I only need to access a small segment of the data at a time. I cannot find a way using this package to just extract a subset of samples using readSignal(chan). Is this possible? I ask because it takes a very very long time to extract all the data for 60 channels for days of data in one go. Thank you.

file_info_long() method is broken.

it returns this error:

C:\Users\davids\AppData\Local\Continuum\Anaconda3\lib\site-packages\pyedflib\edfreader.py in file_info_long(self)
    686         self.file_info()
    687         for ii in np.arange(self.signals_in_file):
--> 688             print("label:", self.getSignalLabel(ii), "fs:",
    689                   self.getSignalFreqs()[ii], "nsamples",
    690                   self.getNSamples()[ii])

AttributeError: 'EdfReader' object has no attribute 'getSignalLabel'

The fix seems to be to change the lines:

    def file_info_long(self):
        self.file_info()
        for ii in np.arange(self.signals_in_file):
            print("label:", self.getSignalLabel(ii), "fs:",
                  self.getSignalFreqs()[ii], "nsamples",
                  self.getNSamples()[ii])

to:

    def file_info_long(self):
        self.file_info()
        for ii in np.arange(self.signals_in_file):
            print("label:", self.getSignalLabels()[ii], "fs:",    # <==Note change here
                  self.getSignalFreqs()[ii], "nsamples",
                  self.getNSamples()[ii])

Sorry about the poor formatting of my issue.

Cannot open file containing accented character on Linux

I have a problem opening edf files with non-ASCII characters on Linux, similar to issue #21.
Opening the file with pyedflib.EdfReader() results in an OSError "file not found" exception - but I can open the same file with python's open().

I checked with strace. This is what I get, when I try check the files existence from python:

stat("/home/data/Xasuro\304\237lu/Xasuroglu.edf", {st_mode=S_IFREG|0660, st_size=129601024, ...}) = 0

And this is the open from pyedflib's C code:

open("/home/data/Xasuro\\u011flu/Xasuroglu.edf", O_RDONLY) = -1 ENOENT (No such file or directory)

The Unicode codepoint 'ğ' is correctly converted int a two byte UTF8 sequence in the stat call. In the open from pyedflib it is converted to \u011f, but the open system call doesn't interpret quotes - it needs plain UTF8 - at least on Linux systems with an UTF8 default locale. Other locales need different encodings. On Windows _wfopen() is recommended for filenames containing non-ASCII characters. So it is starting to get complicated here.

I'm not experienced with the python C bindings so I'm not really sure how this should be fixed. But I think the most portable way would be to open the file from within the python code, then pass the native file handle to the C function and fdopen() it there.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.