edfwrite failure because of 8 byte limit
8 次查看(过去 30 天)
显示 更早的评论
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 个评论
Catherine
2023-11-5
编辑:Catherine
2023-11-5
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);
回答(1 个)
Christopher McCausland
2023-11-5
编辑:Christopher McCausland
2023-11-5
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 个评论
Walter Roberson
2023-11-5
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
2023-11-5
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
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 AI for Signals 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!