Python library for reading and writing EDF+/BDF+ files used for storing biomedical signal data
—
High-level interface for reading EDF, EDF+, BDF, and BDF+ files with comprehensive support for signal data extraction, annotation reading, and header information access. The EdfReader class provides Python-friendly methods with automatic resource management.
Open EDF files with various reading options and automatic resource management through context managers.
class EdfReader:
def __init__(self, file_name: str, annotations_mode: int = READ_ALL_ANNOTATIONS,
check_file_size: int = CHECK_FILE_SIZE):
"""
Initialize EDF reader.
Parameters:
- file_name: str, path to EDF/BDF file
- annotations_mode: int, annotation reading mode (DO_NOT_READ_ANNOTATIONS, READ_ANNOTATIONS, READ_ALL_ANNOTATIONS)
- check_file_size: int, file size checking mode (CHECK_FILE_SIZE, DO_NOT_CHECK_FILE_SIZE, REPAIR_FILE_SIZE_IF_WRONG)
"""
def __enter__(self) -> EdfReader:
"""Context manager entry."""
def __exit__(self, exc_type, exc_val, exc_tb):
"""Context manager exit with automatic cleanup."""
def close(self):
"""Close file handler and release resources."""Usage example:
# Using context manager (recommended)
with pyedflib.EdfReader('data.edf') as f:
# Work with file
signals = f.readSignal(0)
# Manual management
f = pyedflib.EdfReader('data.edf')
try:
signals = f.readSignal(0)
finally:
f.close()Read signal data from individual channels with support for partial reading, digital/physical values, and numpy array output.
def readSignal(self, chn: int, start: int = 0, n: Optional[int] = None,
digital: bool = False) -> np.ndarray:
"""
Read signal data from specified channel.
Parameters:
- chn: int, channel number (0-based)
- start: int, starting sample index
- n: int or None, number of samples to read (None = all remaining)
- digital: bool, return digital values if True, physical values if False
Returns:
numpy.ndarray: Signal data
"""
def getNSamples(self) -> np.ndarray:
"""
Get number of samples for each signal.
Returns:
numpy.ndarray: Array of sample counts per channel
"""Usage example:
with pyedflib.EdfReader('recording.edf') as f:
# Read entire signal from channel 0
signal = f.readSignal(0)
# Read partial signal (samples 1000-2000)
partial = f.readSignal(0, start=1000, n=1000)
# Read digital values instead of physical
digital_signal = f.readSignal(0, digital=True)
# Get sample counts for all channels
sample_counts = f.getNSamples()Extract annotations (events, markers) from EDF+ and BDF+ files with timing information and descriptions.
def readAnnotations(self) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
"""
Read all annotations from file.
Returns:
Tuple containing:
- onset_times: numpy.ndarray, annotation start times in seconds
- durations: numpy.ndarray, annotation durations in seconds
- descriptions: numpy.ndarray, annotation text descriptions
"""Usage example:
with pyedflib.EdfReader('annotated.edf') as f:
onsets, durations, descriptions = f.readAnnotations()
# Process annotations
for i in range(len(onsets)):
print(f"Event at {onsets[i]}s, duration {durations[i]}s: {descriptions[i]}")Retrieve comprehensive file and signal header information including patient data, recording details, and signal parameters.
def getHeader(self) -> Dict:
"""
Get complete file header as dictionary.
Returns:
dict: File header with patient info, recording details, technical data
"""
def getSignalHeader(self, chn: int) -> Dict:
"""
Get header information for specific signal.
Parameters:
- chn: int, channel number
Returns:
dict: Signal header with label, units, sampling rate, calibration
"""
def getSignalHeaders(self) -> List[Dict]:
"""
Get headers for all signals.
Returns:
List[dict]: List of signal headers
"""Access patient demographics, recording metadata, and technical details.
def getPatientName(self) -> str:
"""Get patient name."""
def getPatientCode(self) -> str:
"""Get patient identification code."""
def getPatientAdditional(self) -> str:
"""Get additional patient information."""
def getSex(self) -> str:
"""Get patient sex/gender."""
def getBirthdate(self, string: bool = True) -> Union[str, datetime]:
"""
Get patient birthdate.
Parameters:
- string: bool, return as string if True, datetime object if False
Returns:
str or datetime: Patient birthdate
"""
def getTechnician(self) -> str:
"""Get technician name."""
def getEquipment(self) -> str:
"""Get recording equipment information."""
def getAdmincode(self) -> str:
"""Get administration code."""
def getRecordingAdditional(self) -> str:
"""Get additional recording information."""
def getStartdatetime(self) -> datetime:
"""Get recording start date and time."""
def getFileDuration(self) -> float:
"""
Get total file duration in seconds.
Returns:
float: Duration in seconds
"""Access signal-specific properties including labels, sampling rates, and calibration parameters.
def getSignalLabels(self) -> List[str]:
"""
Get labels for all signals.
Returns:
List[str]: Signal labels
"""
def getLabel(self, chn: int) -> str:
"""
Get label for specific channel.
Parameters:
- chn: int, channel number
Returns:
str: Signal label
"""
def getSampleFrequencies(self) -> np.ndarray:
"""
Get sampling frequencies for all signals.
Returns:
numpy.ndarray: Sample rates in Hz
"""
def getSampleFrequency(self, chn: int) -> float:
"""
Get sampling frequency for specific channel.
Parameters:
- chn: int, channel number
Returns:
float: Sample rate in Hz
"""
def getPhysicalMaximum(self, chn: Optional[int] = None) -> Union[float, np.ndarray]:
"""
Get physical maximum values.
Parameters:
- chn: int or None, channel number (None = all channels)
Returns:
float or numpy.ndarray: Physical maximum value(s)
"""
def getPhysicalMinimum(self, chn: Optional[int] = None) -> Union[float, np.ndarray]:
"""
Get physical minimum values.
Parameters:
- chn: int or None, channel number (None = all channels)
Returns:
float or numpy.ndarray: Physical minimum value(s)
"""
def getDigitalMaximum(self, chn: Optional[int] = None) -> Union[int, np.ndarray]:
"""
Get digital maximum values.
Parameters:
- chn: int or None, channel number (None = all channels)
Returns:
int or numpy.ndarray: Digital maximum value(s)
"""
def getDigitalMinimum(self, chn: Optional[int] = None) -> Union[int, np.ndarray]:
"""
Get digital minimum values.
Parameters:
- chn: int or None, channel number (None = all channels)
Returns:
int or numpy.ndarray: Digital minimum value(s)
"""
def getPhysicalDimension(self, chn: int) -> str:
"""
Get physical dimension (units) for channel.
Parameters:
- chn: int, channel number
Returns:
str: Physical dimension (e.g., 'uV', 'mV')
"""
def getTransducer(self, chn: int) -> str:
"""
Get transducer information for channel.
Parameters:
- chn: int, channel number
Returns:
str: Transducer description
"""
def getPrefilter(self, chn: int) -> str:
"""
Get prefilter information for channel.
Parameters:
- chn: int, channel number
Returns:
str: Prefilter description
"""Access file-level properties for quick information retrieval.
@property
def signals_in_file(self) -> int:
"""Number of signals in the file."""
@property
def datarecords_in_file(self) -> int:
"""Number of data records in the file."""
@property
def file_duration(self) -> float:
"""File duration in seconds."""
@property
def filetype(self) -> int:
"""File type (EDF=0, EDF+=1, BDF=2, BDF+=3)."""
@property
def datarecord_duration(self) -> float:
"""Duration of each data record in seconds."""
@property
def annotations_in_file(self) -> int:
"""Number of annotations in the file."""Usage example:
with pyedflib.EdfReader('data.edf') as f:
# Access file properties
print(f"Signals: {f.signals_in_file}")
print(f"Duration: {f.file_duration} seconds")
print(f"File type: {f.filetype}")
print(f"Data records: {f.datarecords_in_file}")
print(f"Annotations: {f.annotations_in_file}")Convenient methods for displaying file information.
def file_info(self):
"""Print basic file information to console."""
def file_info_long(self):
"""Print detailed file information to console."""Usage example:
with pyedflib.EdfReader('data.edf') as f:
# Display file info
f.file_info()
# Get detailed properties
header = f.getHeader()
labels = f.getSignalLabels()
sample_rates = f.getSampleFrequencies()
print(f"Patient: {f.getPatientName()}")
print(f"Recording duration: {f.getFileDuration()} seconds")
print(f"Channels: {labels}")
print(f"Sample rates: {sample_rates}")# Annotation reading modes
DO_NOT_READ_ANNOTATIONS: int = 0
READ_ANNOTATIONS: int = 1
READ_ALL_ANNOTATIONS: int = 2
# File size checking modes
CHECK_FILE_SIZE: int = 0
DO_NOT_CHECK_FILE_SIZE: int = 1
REPAIR_FILE_SIZE_IF_WRONG: int = 2Install with Tessl CLI
npx tessl i tessl/pypi-pyedflib