Raw export edf file failed
Description of the problem
I tried to export the data to edf format file. It failed.
The code is :
raw = mne.io.read_raw_edf(r"\\NITD-NAS\bci-rw\sleep\sleep-edf-database-expanded-1.0.0\sleep-edf-database-expanded-1.0.0\sleep-cassette\SC4001E0-PSG.edf") raw.export(fname=r"E:\work\NITD\software_test\outputedf.edf", fmt="edf", physical_range="channelwise")
And the error is
Steps to reproduce
raw = mne.io.read_raw_edf(r"\\NITD-NAS\bci-rw\sleep\sleep-edf-database-expanded-1.0.0\sleep-edf-database-expanded-1.0.0\sleep-cassette\SC4001E0-PSG.edf")
raw.export(fname=r"E:\work\NITD\software_test\outputedf.edf", fmt="edf", physical_range="channelwise")
Link to data
No response
Expected results
Get the edf file.
Actual results
Get the edf file.
Additional information
Error.
Hello! 👋 Thanks for opening your first issue here! ❤️ We will try to get back to you soon. 🚴
Hi @BEGINRX ,
I would like to work on this issue. Have you tried any other export formats, or does the error only happen with fmt="edf"? Also, could you share the exact error message to understand the problem better?
Thanks!
Hi. I have tried other formats like "brainvision" and "eeglab". The files were exported successfully. Yes, the error only happened in edf.
The error messages are only the ones listed above. There is no more information.
May I send you the raw file? Or you can download from the website https://physionet.org/content/sleep-edfx/1.0.0/sleep-cassette/#files-panel
To me this looks like a bug in the _round_float_to_8_characters method from edfio. For -2006585738.63211, which is the value of pmin in the provided example data, it returns -2006590000.0.
Script to reproduce:
#!/usr/bin/env python3
import mne
import math
import numpy as np
from typing import Callable
def _round_float_to_8_characters(
value: float,
round_func: Callable[[float], int],
) -> float:
if isinstance(value, int) or value.is_integer():
return value
length = 8
integer_part_length = str(value).find(".")
if integer_part_length == length:
return round_func(value)
factor = 10 ** (length - 1 - integer_part_length)
return round_func(value * factor) / factor
# https://physionet.org/files/sleep-edfx/1.0.0/sleep-cassette/SC4001E0-PSG.edf?download
raw = mne.io.read_raw_edf('SC4001E0-PSG.edf')
# relevant code from: _export_raw_edf_bdf()
units = dict(
eeg="uV", ecog="uV", seeg="uV", eog="uV", ecg="uV", emg="uV", bio="uV", dbs="uV"
)
ch_types = np.array(raw.get_channel_types())
ch_types_phys_max = dict()
ch_types_phys_min = dict()
for _type in np.unique(ch_types):
_picks = [n for n, t in zip(raw.ch_names, ch_types) if t == _type]
_data = raw.get_data(units=units, picks=_picks)
ch_types_phys_max[_type] = _data.max()
ch_types_phys_min[_type] = _data.min()
ch_type = ch_types[0]
pmin = ch_types_phys_min[ch_type]
pmax = ch_types_phys_max[ch_type]
if pmax == pmin:
pmax = pmin + 1
prange = pmin, pmax
print("before _round_float_to_8_characters:", pmin)
# functions that are called by EdfSignal constructor
x = _round_float_to_8_characters(pmin, math.floor)
if float(x).is_integer():
x = int(x)
print("after _round_float_to_8_characters:", x)
# trigger the error
raw.export("output.edf")
Looking at the physical_range of the signals using edfio directly, it seems that -2006585738.63211 is wrong in the first place.
#!/usr/bin/env python3
import edfio
edf = edfio.read_edf("SC4001E0-PSG.edf")
for sig in edf.signals:
print(sig.physical_dimension)
print(sig.physical_range)
print()
output:
uV
_FloatRange(min=-192.0, max=192.0)
uV
_FloatRange(min=-197.0, max=196.0)
uV
_FloatRange(min=-1009.0, max=1009.0)
_FloatRange(min=-2048.0, max=2047.0)
uV
_FloatRange(min=-5.0, max=5.0)
DegC
_FloatRange(min=34.0, max=40.0)
_FloatRange(min=-2047.0, max=2048.0)
I think the issue is with the .edf file itself. The header does not specify an unit for the "Resp oro-nasal" channel and physical range min -2048, but the actual data min is -2006585738.63; but -2006585738.63 does not fit in the 16 bits for digital_min.