Skip to content

Introduction

openseize.file_io.edf

Tools for reading and writing EEG metadata and data in the European Data Format (EDF/EDF+). This module contains:

- Header: An extended dictionary representation of and EDF header
- Reader: A reader of EDF data and metadata
- Writer: A writer of EDF data and metadata
- splitter: A function to split EDF files into multiple EDF files.

Header

The Header section of an EDF file is partitioned into sequential sections containing metadata. Each section has a specified number of bytes used to encode an an 'ascii' string. For example the first two sections of the header are:

***************************************
8 bytes | 80 bytes | ................
***************************************
The first 8 bytes are the EDF version string and the next 80 bytes are the patient_id string. The full specification of the EDF header can be found here: https://www.edfplus.info/specs/edf.html. A Header instance, is an extended dictionary keyed on the field name from the EDF specification (i.e. version, patient, etc) with a value that has been decoded from the file at path like this:
{'version': 'EDF+', 'patient': 'mouse_1', ...}

Reader

EDF files are divided into header and data records sections. Each data record contains measured signals and annotation signals stored sequentially. Below is a sample layout of a single data record:

***********************************************************
Ch0 samples | Ch1 samples | Ch2 samples | ... | Annotations
***********************************************************
To distinguish numerical signals from annotation signals, we refer to numerical signals as channels. Currently, readers does not support the reading of annotation signals stored in the data records.

For details on the EDF/+ file specification please see; https://www.edfplus.info/specs/index.html

The reader supports reading EEG data and metadata from an EDF file with and without context management. If opened outside of context management, you should close this Reader's instance manually by calling the 'close' method to recover open file resources when you finish processing a file.

Examples:

>>> # Read samples from an EDF with Context management
>>> from openseize.demos import paths
>>> filepath = paths.locate('recording_001.edf')
>>> from openseize.io.edf import Reader
>>> # open a reader using context management and reading 120 samples
>>> # from all 4 channels
>>> with Reader(filepath) as infile:
>>>     x = infile.read(start=0, stop=120)
>>> print(x.shape)
... (4, 120)
>>> # open the reader without context management
>>> reader = Reader(filepath)
>>> # set reader to read only channels 0 and 2 data
>>> reader.channels = [0, 2]
>>> # read samples 0 to 99 from channels 0 and 2
>>> y = reader.read(start=0, stop=99)
>>> print(y.shape)
... (2, 99)
>>> # Read samples from an EDF without context management
>>> reader = Reader(filepath)
>>> y = reader.read(start=10, stop=61)
>>> # view the reader's Header instance
>>> print(reader.header)
>>> # when done with the reader, you should close it to recover
>>> # resources
>>> reader.close()

Writer

A Writer is a context manager for writing EEG data and metadata to an EDF binary file. Unlike Readers it must be opened under the context management protocol. Importantly, this writer does not currently support writing annotations to an EDF file.

Examples:

>>> from openseize.demos import paths
>>> filepath = paths.locate('recording_001.edf')
>>> # Create a reader that will read only channels [0, 1]
>>> # and write out these channels to a new file
>>> writepath = paths.data_dir.joinpath('subset_001.edf')
>>> with Reader(filepath) as reader:
>>>     with Writer(writepath) as writer:
>>>         writer.write(reader.header, reader, channels=[0, 1])

Splitter

A tool for splitting an EDF into multiple EDFs each containing different channels of the unsplit EDF. In particular, this tool is useful for partitioning an EDF with channels from different subjects into multiple single subject EDFs. The original 'joined' EDF is left unmodified.