Python library for reading and writing EDF+/BDF+ files used for storing biomedical signal data
npx @tessl/cli install tessl/pypi-pyedflib@0.1.0A 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.
pip install pyEDFlibimport pyedflibFor high-level functions:
from pyedflib import highlevel
# or
import pyedflib.highlevel as hlFor data utilities:
from pyedflib import data
# or
import pyedflib.dataFor specific classes and functions:
from pyedflib import EdfReader, EdfWriter
from pyedflib.highlevel import read_edf, write_edfimport pyedflib
import numpy as np
from pyedflib import highlevel
# Reading an EDF file (low-level)
with pyedflib.EdfReader('sample.edf') as f:
# Get basic file info
n_channels = f.signals_in_file
sample_freqs = f.getSampleFrequencies()
signal_labels = f.getSignalLabels()
# Read signal data
signal_data = []
for i in range(n_channels):
signal_data.append(f.readSignal(i))
# Reading an EDF file (high-level)
signals, signal_headers, header = highlevel.read_edf('sample.edf')
# Writing an EDF file (low-level)
channel_info = [
{'label': 'EEG Fp1', 'dimension': 'uV', 'sample_frequency': 100,
'physical_min': -500.0, 'physical_max': 500.0,
'digital_min': -2048, 'digital_max': 2047},
{'label': 'EEG Fp2', 'dimension': 'uV', 'sample_frequency': 100,
'physical_min': -500.0, 'physical_max': 500.0,
'digital_min': -2048, 'digital_max': 2047}
]
with pyedflib.EdfWriter('output.edf', 2, file_type=pyedflib.FILETYPE_EDFPLUS) as f:
f.setSignalHeaders(channel_info)
# Write sample data
data_ch1 = np.random.normal(0, 50, 1000) # 10 seconds at 100 Hz
data_ch2 = np.random.normal(0, 50, 1000)
f.writeSamples([data_ch1, data_ch2])
# Writing an EDF file (high-level)
signals = np.random.normal(0, 50, (2, 1000)) # 2 channels, 1000 samples
signal_headers = highlevel.make_signal_headers(['EEG Fp1', 'EEG Fp2'], sample_frequency=100)
highlevel.write_edf('output.edf', signals, signal_headers)pyEDFlib is built on a layered architecture:
EdfReader and EdfWriter provide Python-friendly interfaces with context managers, automatic resource management, and convenient methodsCyEdfReader and C extension functions offer direct access to the underlying EDFlib C library for maximum performancepyedflib.highlevel for common operations like reading/writing entire files, file manipulation, and data conversionpyedflib.data for development and testingThis 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.
High-level interface for reading EDF, EDF+, BDF, and BDF+ files with support for signal data extraction, annotation reading, and comprehensive header information access.
class EdfReader:
def __enter__(self) -> EdfReader: ...
def __exit__(self, exc_type, exc_val, exc_tb): ...
def readSignal(self, chn: int, start: int = 0, n: Optional[int] = None, digital: bool = False) -> np.ndarray: ...
def readAnnotations(self) -> Tuple[np.ndarray, np.ndarray, np.ndarray]: ...
def getHeader(self) -> Dict: ...
def getSignalHeaders(self) -> List[Dict]: ...Interface for creating and writing EDF, EDF+, BDF, and BDF+ files with comprehensive header configuration, signal data writing, and annotation support.
class EdfWriter:
def __init__(self, file_name: str, n_channels: int, file_type: int = FILETYPE_EDFPLUS): ...
def __enter__(self) -> EdfWriter: ...
def __exit__(self, exc_type, exc_val, exc_tb): ...
def setSignalHeaders(self, signalHeaders: List[Dict]): ...
def writeSamples(self, data_list: Union[List[np.ndarray], np.ndarray], digital: bool = False): ...
def writeAnnotation(self, onset_in_seconds: Union[int, float], duration_in_seconds: Union[int, float], description: str): ...Convenience functions for complete file operations, data conversion, file manipulation, and batch processing tasks.
def read_edf(edf_file: str, ch_nrs: Optional[Union[List[int], int]] = None,
ch_names: Optional[Union[List[str], str]] = None, digital: bool = False,
verbose: bool = False) -> Tuple[Union[np.ndarray, List[np.ndarray]], List[dict], dict]: ...
def write_edf(edf_file: str, signals: Union[np.ndarray, List[np.ndarray]], signal_headers: List[Dict],
header: Optional[Dict] = None, digital: bool = False,
file_type: int = -1) -> bool: ...
def make_header(technician: str = '', recording_additional: str = '', patientname: str = '',
patient_additional: str = '', patientcode: str = '', equipment: str = '',
admincode: str = '', sex: str = '', startdate: Optional[datetime] = None,
birthdate: Union[str, datetime] = '') -> dict: ...
def make_signal_headers(list_of_labels: List[str], dimension: str = 'uV',
sample_frequency: Optional[Union[int, float]] = 256,
physical_min: float = -200.0, physical_max: float = 200.0) -> List[dict]: ...Direct access to underlying C library functions for maximum performance and fine-grained control over file operations and data handling.
class CyEdfReader:
def __init__(self, file_name: str, annotations_mode: int = READ_ANNOTATIONS,
check_file_size: int = CHECK_FILE_SIZE): ...
def read_digital_signal(self, signalnum: int, start: int, n: int, sigbuf: np.ndarray): ...
def readsignal(self, signalnum: int, start: int, n: int, sigbuf: np.ndarray): ...
def open_file_writeonly(path: str, filetype: int, number_of_signals: int) -> int: ...
def write_physical_samples(handle: int, buf: np.ndarray) -> int: ...
def close_file(handle: int) -> int: ...Test data and sample files for development and testing.
def test_generator() -> EdfReader:
"""Get sample EDF file for testing."""
def get_generator_filename() -> str:
"""Get path to test EDF file."""FILETYPE_EDF: int = 0 # Standard EDF format
FILETYPE_EDFPLUS: int = 1 # EDF+ format with annotations
FILETYPE_BDF: int = 2 # BDF format (24-bit)
FILETYPE_BDFPLUS: int = 3 # BDF+ format with annotationsDO_NOT_READ_ANNOTATIONS: int = 0 # Skip annotation reading
READ_ANNOTATIONS: int = 1 # Read some annotations
READ_ALL_ANNOTATIONS: int = 2 # Read all annotationsCHECK_FILE_SIZE: int = 0 # Verify file size
DO_NOT_CHECK_FILE_SIZE: int = 1 # Skip file size check
REPAIR_FILE_SIZE_IF_WRONG: int = 2 # Auto-repair incorrect file sizeopen_errors: Dict[int, str] # Error codes for file opening
write_errors: Dict[int, str] # Error codes for file writingdef lib_version() -> str:
"""Get underlying edflib C library version."""