Attaching event labels from excel to EDF file - how to interpolate and merge data?
8 views (last 30 days)
Show older comments
Hello!
I have recorded ECG data with Acqknowledge (BioPac) and want to analyse the data in Matlab. Having used different experimental conditions, I have a number of event labels indicating the onset of a particular stimulus which are visible in Acqknowledge but have to be exported separatly to Matlab.
The ECG data can be exported from Acq to EDF which is a file the toolbox I am using can read. The event labels are stored in a .xls file as a table format.
Now I face the challenge of attaching my event labels to my ECG data which I then want to save as a new EDF file for analysing the data depending on the respective experimental conditions (indicated by the labels).
My ecgData comes as a timetalbe format (apparently) with the recorded time in seconds as a first column, followed by four columns representing my channels (ECG, rate, digital input etc.)
My eventlabel data is in numeric values (codes for e.g., '255', '254'...) and is connected to a column indicating the even onset in seconds.
I am rather unexperienced in Matlab, so I tried a few things which did not work out yet.
data = edfread('T1_subject2_HRV.edf'); %read my data
ecgData = data(:, 3); % extract the exgData which is in column 3, resulting in a time object (?) with both recording time and ECG data in two columns
timeData = ecgData.Properties.RowTimes % I try to access time stmaps which results in a new time object with only the seconds of recording
% then I read the event labels in my xls file and extract the tie and event column separatly
table = readtable('subj2_T1_events.xlsx'); % Assuming event labels are in column A
timeColumn = table.Time
eventColumn = table.Label
% Convert time values to same format
timeInSecondsEvents = str2double(strrep(table.Time, ' sec', ''));
timeInSecondsECG = seconds(timeDataECG);
% Remove NaN I had left in my event label data because of some weird reason
validIndices = isfinite(eventColumn) & isfinite(timeInSecondsEvents);
eventColumnValid = eventColumn(validIndices);
timeInSecondsValidEvents = timeInSecondsEvents(validIndices);
Now I would like to merye my eventColumnValid back with my timeinSecondsValidEvents and attach these to my timeinSecondsECG and to my ecgData.
One idea was to use an if loop and let every column compare the time stamps of ECG recording with the event label time and insert the label when the time would match but I guess my computer would give up on me going through 3000 columns per participant.
% I stumbled across the inperpolate function trying to find the nearest neighbour between them.
matchedEventLabelsInSeconds = interp1(eventColumnValid, timeInSecondsValidEvents, timeInSecondsECG', 'extrap');
However, this produces the following error:
Error using interp1>parseinputs
An interpolation method must be specified with 'extrap'.
Error in interp1 (line 112)
parseinputs(X,V,penultimate,last,nargin,ndataarg,pp);
and I also need to attach my ecgData back to it which still lingers around in a timetable.
I am very happy for any suggestion on trying out something different or resolving this error in the first place.
Thank you and best regards
Linn
0 Comments
Answers (2)
Sanjana
on 30 Aug 2023
Hi Linn,
I understand that you are trying to merge the ECG data read from “. edf” file and the data read from the “.xls” file containing event labels along with the onset durations, based on the common “recorded time column” in both the tables.
To achieve the above you can use, “join” function specifying the “keys” argument to be the name of the column that is common to both the tables, that is the “recorded time” column.
Please refer to the following documentation, for further information,
Hope this helps!
Regards,
Sanjana
0 Comments
Seth Furman
on 14 Sep 2023
Read event data and convert to an event table
Starting in R2023a, you can represent event data as an event table (eventtable).
% Ordinarily you'd use readtimetable here instead of readtable, but
% readtimetable does not currently support row-times of the format
% "<number> sec". You can avoid this by using row-times of the format
% "hh:mm:ss".
%
% See https://www.mathworks.com/help/matlab/ref/duration.html#mw_7dddd595-1be8-452b-8270-5589013aa7d4
%
% For example,
%
% Labels = [255;254];
% tt = timetable(seconds([1;2]),Labels);
% tt.Time.Format = "hh:mm:ss";
% writetimetable(tt,"data.xlsx");
%
% opts = detectImportOptions("data.xlsx");
% opts = setvaropts(opts,"Time",Type="duration",DurationFormat="hh:mm:ss");
% tt2 = readtimetable("data.xlsx",opts);
evnts = readtable("events.xlsx",TextType="string")
% At the moment, you can't directly convert strings with the format
% "<number> sec" into durations. datetime, however, allows you to specify
% many different formats, so you can use the datetime constructor to
% convert the strings into datetimes and then pull out the time of day to
% get the duration.
evnts.Time = timeofday(datetime(evnts.Time,InputFormat="ss 'sec'"));
% Now that we've converted evnts.Time into a duration array, we can convert
% the table into a timetable.
evnts = table2timetable(evnts)
evnts = rmmissing(evnts) % Remove rows with missing data.
% Convert the timetable into an eventtable.
evnts = eventtable(evnts,EventLabelsVariable="Labels")
Read in the EDF data as a timetable and attach the event table
Event tables can be attached to a timetable using the new Events timetable property.
tt = edfread("example.edf")
tt.Properties.Events = evnts
Use the eventfilter subscripter to select rows corresponding to given events
% Get the rows of the timetable corresponding to the event whose label is 255.
eventLabelOfInterest = 255;
tt(eventfilter(eventLabelOfInterest),:)
% Get all rows of the timetable corresponding to any event.
tt(eventfilter(),:)
Add and synchronize variables from the attached event table to the timetable
Data from an event table attached to a timetable can be added and synchronized to the timetable using syncevents.
tt = syncevents(tt)
Aside
(1) You say that your event label data are numeric codes. If you have a fixed number of them, you can consider representing them as categoricals instead of numbers. For example,
evnts.Labels = categorical(evnts.Labels)
(2) Your example has the following line.
table = readtable("...");
table is a bad variable name in MATLAB since it is the name of a class. Prefer something else, like tbl.
0 Comments
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!