edfwrite failure because of 8 byte limit

9 views (last 30 days)
I am trying convert some data to an EDF with the following code (per this page edf_link):
fs = 250;
data = data_streams{i};
Undefined variable 'data_streams'.
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
Clay Smyth
Clay Smyth on 18 Aug 2023
Thanks for the reply, here is the values of the variable:
Catherine
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);

Sign in to comment.

Answers (1)

Christopher McCausland
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!
A similar issue can be found here.
Christopher
  2 Comments
Walter Roberson
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
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.
You are correct, as always @Walter Roberson, thank you for the clarity though!
@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

Sign in to comment.

Tags

Products


Release

R2022a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!