Skip to content

Resolution issue with EDF export #12493

@cbrnr

Description

@cbrnr

Description of the problem

When exporting this BDF file to EDF, the amplitude resolution seems to decrease a lot (amplitude values are clearly discretized). I suspect that maybe this has to do with some physical to digital min/max setting, which by default is set to "auto". Or maybe the range of the original data is too large and cannot be accurately represented with 16 bits (BDF uses 24 bits).

>>> raw.describe()
<RawEDF | S01.bdf, 73 x 1939456 (3788.0 s), ~1.05 GB, data loaded>
ch  name    type  unit        min         Q1     median         Q3        max
 0  Fp1     EEG   µV    -28733.96  -28283.90  -28180.43  -27993.25  -26932.31
 1  AF7     EEG   µV    -22318.10  -21375.51  -20833.26  -20595.17  -19586.39
 2  AF3     EEG   µV    -11227.59  -10846.75  -10493.43   -9618.47   -8873.50
 3  F1      EEG   µV    -19847.79  -19601.29  -19297.20  -18904.51  -18461.83
...
>>> raw_edf.describe()
<RawEDF | S01.edf, 72 x 1939456 (3788.0 s), ~59 kB, data not loaded>
ch  name  type  unit        min         Q1     median         Q3        max
 0  Fp1   EEG   µV    -28733.76  -28283.63  -28182.47  -27995.34  -26933.23
 1  AF7   EEG   µV    -22315.59  -21374.87  -20833.70  -20595.99  -19584.46
 2  AF3   EEG   µV    -11229.21  -10844.83  -10495.85   -9620.87   -8872.34
 3  F1    EEG   µV    -19847.46  -19599.63  -19296.17  -18906.73  -18461.66
...

For channel 0, the range is approximately 52000µV, therefore the resolutions are:

>>> 52000/2**16  # EDF
0.79345703125
>>> 52000/2**24  # BDF
0.0030994415283203125

So yes, it looks like the range is too large for EDF. Should we maybe issue a warning in such cases?

Edit: I actually didn't see the minus sign for the max value, so the range for channel 0 is 1800µV. However, the way we're currently exporting to EDF is to use the global physical min and max across all channels, which can yield a large range if the channels vary wildly in their offsets. So the conclusion is still correct, EDF cannot represent such a large range with sufficient accuracy (only 2¹⁶ values as compared to 2²⁴).

Steps to reproduce

The data set S01.bdf is linked in the first paragraph.

import mne

raw = mne.io.read_raw("S01.bdf")
raw.plot(duration=1, n_channels=1)  # plot 1
raw.export("S01.edf", overwrite=True)
raw_edf = mne.io.read_raw("S01.edf")
raw_edf.plot(duration=1, n_channels=1)  # plot 2

Expected results

The data in the exported EDF file should be identical to the original BDF file.

Actual results

This is a plot of a portion of the original BDF data (plot 1 in the MWE):
plot1
And here's the plot of the exported EDF file (plot 2 in the MWE):
plot2

@hofaflo what's your take on this issue?

Additional information

Platform             macOS-14.3.1-arm64-arm-64bit
Python               3.12.2 (main, Feb 14 2024, 07:24:33) [Clang 15.0.0 (clang-1500.1.0.2.5)]
Executable           /Users/clemens/.pyenv/versions/3.12.2/envs/mne/bin/python
CPU                  arm (12 cores)
Memory               32.0 GB

Core
├☑ mne               1.7.0.dev26+g7bf1b4ab7 (devel, latest release is 1.6.1)
├☑ numpy             1.26.4 (OpenBLAS 0.3.23.dev with 12 threads)
├☑ scipy             1.12.0
└☑ matplotlib        3.8.3 (backend=MacOSX)

Numerical (optional)
├☑ sklearn           1.4.1.post1
└☐ unavailable       numba, nibabel, nilearn, dipy, openmeeg, cupy, pandas

Visualization (optional)
└☐ unavailable       pyvista, pyvistaqt, vtk, qtpy, ipympl, pyqtgraph, mne-qt-browser, ipywidgets, trame_client, trame_server, trame_vtk, trame_vuetify

Ecosystem (optional)
└☐ unavailable       mne-bids, mne-nirs, mne-features, mne-connectivity, mne-icalabel, mne-bids-pipeline, neo

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions