edfwrite failure because of 8 byte limit
1 view (last 30 days)
Show older comments
fs = 250;
data = data_streams{i};
out_dir = '[redacted]';
out_file = data_names{i};
out_file_full = fullfile(out_dir, strcat(out_file,'.edf'));
hdr = edfheader("EDF+");
hdr.NumDataRecords = 1;
hdr.NumSignals = 1;
hdr.SignalLabels = ["SubCTX"];
hdr.DataRecordDuration = seconds(length(data(:,1))/fs);
hdr.PhysicalDimensions = repelem("mV",1);
hdr.PhysicalMin = min(data);
hdr.PhysicalMax = max(data);
hdr.DigitalMin = -32768;
hdr.DigitalMax = 32767;
edfw = edfwrite(out_file_full,hdr,data);
But run into the following error:
_______
Error using signal.internal.edf.write.validateFieldBytes
Value of "DataRecordDuration" field must be less than or equal to 8 bytes. See edfheader documentation for more information.
Error in edfwrite/createFile (line 1685)
signal.internal.edf.write.validateFieldBytes(value, fieldIndex, ...
Error in edfwrite (line 499)
[obj, fileInfo] = createFile(obj, filename, hdr,...
Error in create_edfs_from_OFF_data (line 45)
edfw = edfwrite(out_file_full,hdr,data);
________
I do not know how to avoid this, because the output for
seconds()
is always 10 bytes.
Example:
tmp = seconds(1);
disp(whos('tmp').bytes)
Any guidance would be very welcomed! Thanks in advance.
3 Comments
Catherine
on 5 Nov 2023
Edited: Catherine
on 5 Nov 2023
Hi, @Clay Smyth! I was struggling with this same issue and just found a workable solution — hopefully still useful for you :)
My theory is that it's not the size of the output of seconds() that matters, but rather the size of the object that you put into it. I tried seconds(1) and the script ran successfully despite seconds(1) being 10 bytes. However, when I tried it with the actual length of my data in milliseconds (which was a 10 byte double before I turned it into a duration) it failed. That being said, this theory didn't hold for when I converted my data length in milliseconds to seconds, which was also an 8 byte double, and set DataRecordDuration to that.
But anyhoo, this workaround is working with multiple files for me and can maybe work for you too:
%create duration (my data is in milliseconds)
data_duration = seconds(width(sig_data)/256);
%turns into a double
hours = hours(data_duration);
%round hours to 1 after decimal point, whos('hours_rounded') = 8 bytes
hours_rounded = round(hours,2);
%add to header as a duration
header.DataRecordDuration = hours(hours_rounded);
Answers (1)
Christopher McCausland
on 5 Nov 2023
Edited: Christopher McCausland
on 5 Nov 2023
Hi all,
I have had a look at the above, from the documentation in edfheader.DataRecordDuration the input should be [a] "Duration of each data record, returned as a duration scalar."
@Catherine's solotion does exactly that, takes a duration value and then returns it back as a double (i.e. a scalar).
@Walter Roberson, Is there anyway to get this flagged with the QA team to make the discription a little more indepth/ add an example? Scaler conversion is required several edfheader inputs and the scalar part is easy to miss!
Christopher
2 Comments
Walter Roberson
on 5 Nov 2023
The original poster had
hdr.DataRecordDuration = seconds(length(data(:,1))/fs);
data(:,1) is a vector, but length() of that is going to be a scalar; fs is a scalar so the result of the division will be a scalar. seconds() of a scalar will be a scalar duration.
hdr.DataRecordDuration = seconds(4.22)
which tells us that a duration is expected (or at least is one of the valid options.)
Christopher McCausland
on 5 Nov 2023
Hi Walter,
Just gave this a go in 2023b and the error message has been updated. It's now a lot more direct (which is far less confusing):
Error using edfwrite
Expected dataRecordDuration of header structure to be one of these types:
duration
Instead its type was double.
@Clay Smyth I would also have a look at the orignal specification for .edf, if you want to know why it's limited to 8 bytes.Here is a link.
Christopher
See Also
Categories
Find more on AI for Signals in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!