Python library for reading and writing EDF+/BDF+ files used for storing biomedical signal data
npx @tessl/cli install tessl/pypi-pyedflib@0.1.00
# pyEDFlib
1
2
A Python library for reading and writing EDF+/BDF+ (European Data Format) files used for storing biomedical signal data such as EEG, ECG, and other physiological measurements. pyEDFlib provides both high-level Python interfaces and low-level C extensions for efficient file operations, making it essential for researchers and developers working with biomedical time-series data.
3
4
## Package Information
5
6
- **Package Name**: pyEDFlib
7
- **Language**: Python
8
- **Installation**: `pip install pyEDFlib`
9
10
## Core Imports
11
12
```python
13
import pyedflib
14
```
15
16
For high-level functions:
17
18
```python
19
from pyedflib import highlevel
20
# or
21
import pyedflib.highlevel as hl
22
```
23
24
For data utilities:
25
26
```python
27
from pyedflib import data
28
# or
29
import pyedflib.data
30
```
31
32
For specific classes and functions:
33
34
```python
35
from pyedflib import EdfReader, EdfWriter
36
from pyedflib.highlevel import read_edf, write_edf
37
```
38
39
## Basic Usage
40
41
```python
42
import pyedflib
43
import numpy as np
44
from pyedflib import highlevel
45
46
# Reading an EDF file (low-level)
47
with pyedflib.EdfReader('sample.edf') as f:
48
# Get basic file info
49
n_channels = f.signals_in_file
50
sample_freqs = f.getSampleFrequencies()
51
signal_labels = f.getSignalLabels()
52
53
# Read signal data
54
signal_data = []
55
for i in range(n_channels):
56
signal_data.append(f.readSignal(i))
57
58
# Reading an EDF file (high-level)
59
signals, signal_headers, header = highlevel.read_edf('sample.edf')
60
61
# Writing an EDF file (low-level)
62
channel_info = [
63
{'label': 'EEG Fp1', 'dimension': 'uV', 'sample_frequency': 100,
64
'physical_min': -500.0, 'physical_max': 500.0,
65
'digital_min': -2048, 'digital_max': 2047},
66
{'label': 'EEG Fp2', 'dimension': 'uV', 'sample_frequency': 100,
67
'physical_min': -500.0, 'physical_max': 500.0,
68
'digital_min': -2048, 'digital_max': 2047}
69
]
70
71
with pyedflib.EdfWriter('output.edf', 2, file_type=pyedflib.FILETYPE_EDFPLUS) as f:
72
f.setSignalHeaders(channel_info)
73
74
# Write sample data
75
data_ch1 = np.random.normal(0, 50, 1000) # 10 seconds at 100 Hz
76
data_ch2 = np.random.normal(0, 50, 1000)
77
78
f.writeSamples([data_ch1, data_ch2])
79
80
# Writing an EDF file (high-level)
81
signals = np.random.normal(0, 50, (2, 1000)) # 2 channels, 1000 samples
82
signal_headers = highlevel.make_signal_headers(['EEG Fp1', 'EEG Fp2'], sample_frequency=100)
83
highlevel.write_edf('output.edf', signals, signal_headers)
84
```
85
86
## Architecture
87
88
pyEDFlib is built on a layered architecture:
89
90
- **High-level Classes**: `EdfReader` and `EdfWriter` provide Python-friendly interfaces with context managers, automatic resource management, and convenient methods
91
- **Low-level Extensions**: Cython-based `CyEdfReader` and C extension functions offer direct access to the underlying EDFlib C library for maximum performance
92
- **High-level Functions**: Convenience functions in `pyedflib.highlevel` for common operations like reading/writing entire files, file manipulation, and data conversion
93
- **Data Utilities**: Test data and sample files in `pyedflib.data` for development and testing
94
95
This design enables both ease of use for common tasks and fine-grained control for performance-critical applications, while maintaining compatibility with the established EDF/BDF standards used in biomedical research.
96
97
## Capabilities
98
99
### EDF File Reading
100
101
High-level interface for reading EDF, EDF+, BDF, and BDF+ files with support for signal data extraction, annotation reading, and comprehensive header information access.
102
103
```python { .api }
104
class EdfReader:
105
def __enter__(self) -> EdfReader: ...
106
def __exit__(self, exc_type, exc_val, exc_tb): ...
107
def readSignal(self, chn: int, start: int = 0, n: Optional[int] = None, digital: bool = False) -> np.ndarray: ...
108
def readAnnotations(self) -> Tuple[np.ndarray, np.ndarray, np.ndarray]: ...
109
def getHeader(self) -> Dict: ...
110
def getSignalHeaders(self) -> List[Dict]: ...
111
```
112
113
[EDF Reading](./edf-reading.md)
114
115
### EDF File Writing
116
117
Interface for creating and writing EDF, EDF+, BDF, and BDF+ files with comprehensive header configuration, signal data writing, and annotation support.
118
119
```python { .api }
120
class EdfWriter:
121
def __init__(self, file_name: str, n_channels: int, file_type: int = FILETYPE_EDFPLUS): ...
122
def __enter__(self) -> EdfWriter: ...
123
def __exit__(self, exc_type, exc_val, exc_tb): ...
124
def setSignalHeaders(self, signalHeaders: List[Dict]): ...
125
def writeSamples(self, data_list: Union[List[np.ndarray], np.ndarray], digital: bool = False): ...
126
def writeAnnotation(self, onset_in_seconds: Union[int, float], duration_in_seconds: Union[int, float], description: str): ...
127
```
128
129
[EDF Writing](./edf-writing.md)
130
131
### High-Level Operations
132
133
Convenience functions for complete file operations, data conversion, file manipulation, and batch processing tasks.
134
135
```python { .api }
136
def read_edf(edf_file: str, ch_nrs: Optional[Union[List[int], int]] = None,
137
ch_names: Optional[Union[List[str], str]] = None, digital: bool = False,
138
verbose: bool = False) -> Tuple[Union[np.ndarray, List[np.ndarray]], List[dict], dict]: ...
139
def write_edf(edf_file: str, signals: Union[np.ndarray, List[np.ndarray]], signal_headers: List[Dict],
140
header: Optional[Dict] = None, digital: bool = False,
141
file_type: int = -1) -> bool: ...
142
def make_header(technician: str = '', recording_additional: str = '', patientname: str = '',
143
patient_additional: str = '', patientcode: str = '', equipment: str = '',
144
admincode: str = '', sex: str = '', startdate: Optional[datetime] = None,
145
birthdate: Union[str, datetime] = '') -> dict: ...
146
def make_signal_headers(list_of_labels: List[str], dimension: str = 'uV',
147
sample_frequency: Optional[Union[int, float]] = 256,
148
physical_min: float = -200.0, physical_max: float = 200.0) -> List[dict]: ...
149
```
150
151
[High-level Functions](./high-level-functions.md)
152
153
### Low-Level Operations
154
155
Direct access to underlying C library functions for maximum performance and fine-grained control over file operations and data handling.
156
157
```python { .api }
158
class CyEdfReader:
159
def __init__(self, file_name: str, annotations_mode: int = READ_ANNOTATIONS,
160
check_file_size: int = CHECK_FILE_SIZE): ...
161
def read_digital_signal(self, signalnum: int, start: int, n: int, sigbuf: np.ndarray): ...
162
def readsignal(self, signalnum: int, start: int, n: int, sigbuf: np.ndarray): ...
163
164
def open_file_writeonly(path: str, filetype: int, number_of_signals: int) -> int: ...
165
def write_physical_samples(handle: int, buf: np.ndarray) -> int: ...
166
def close_file(handle: int) -> int: ...
167
```
168
169
[Low-level Interface](./low-level-interface.md)
170
171
## Data Utilities
172
173
Test data and sample files for development and testing.
174
175
```python { .api }
176
def test_generator() -> EdfReader:
177
"""Get sample EDF file for testing."""
178
179
def get_generator_filename() -> str:
180
"""Get path to test EDF file."""
181
```
182
183
## Constants
184
185
### File Types
186
187
```python { .api }
188
FILETYPE_EDF: int = 0 # Standard EDF format
189
FILETYPE_EDFPLUS: int = 1 # EDF+ format with annotations
190
FILETYPE_BDF: int = 2 # BDF format (24-bit)
191
FILETYPE_BDFPLUS: int = 3 # BDF+ format with annotations
192
```
193
194
### Annotation Reading Options
195
196
```python { .api }
197
DO_NOT_READ_ANNOTATIONS: int = 0 # Skip annotation reading
198
READ_ANNOTATIONS: int = 1 # Read some annotations
199
READ_ALL_ANNOTATIONS: int = 2 # Read all annotations
200
```
201
202
### File Size Check Options
203
204
```python { .api }
205
CHECK_FILE_SIZE: int = 0 # Verify file size
206
DO_NOT_CHECK_FILE_SIZE: int = 1 # Skip file size check
207
REPAIR_FILE_SIZE_IF_WRONG: int = 2 # Auto-repair incorrect file size
208
```
209
210
### Error Dictionaries
211
212
```python { .api }
213
open_errors: Dict[int, str] # Error codes for file opening
214
write_errors: Dict[int, str] # Error codes for file writing
215
```
216
217
### Utility Functions
218
219
```python { .api }
220
def lib_version() -> str:
221
"""Get underlying edflib C library version."""
222
```