Assigning Columns to a table without using loops - and perform i.e. diff on a column

Hello, I have an events log that I want to be able to pull out relevant times and types of triggers into an array of some sort. As its a mixture of text and numbers I originally thought of using a cell array, but have since preferred the idea of using a table.
Ultimately I want a table showing
[count, FrameNumber, (AbsTime-AbsTime_from_1st event) trigger type
All of this info is available in the events.Data and events.type fields
This was my basic attempt to get going
Type=events(:).Type
AbsTime=datetime(events(:).Data.AbsTime)
T0=datetime(events(1).Data.AbsTime)
D=diff(T0)
table(Type,AbsTime,T0,D)
But I see an error
Intermediate dot '.' indexing produced a comma-separated list with 5 values, but it must produce a single value when followed by subsequent indexing
operations.
Error in HTS_TestSoftware/StopVidButtonPushed (line 8572)
AbsTime=datetime(events(:).Data.AbsTime)
Does this mean I have to use loops then?
Also how do I include the diff of the abs time to get each individual time difference?
events =
1×5 struct array with fields:
Type
Data
ans =
struct with fields:
% Here is events.Data-----------------------------------------------
AbsTime: [2025 2 14 15 22 54.8366]
FrameNumber: 0
RelativeFrame: 0
TriggerIndex: 0
ans =
struct with fields:
AbsTime: [2025 2 14 15 22 55.0519]
FrameNumber: 0
RelativeFrame: 0
TriggerIndex: 0
ans =
struct with fields:
AbsTime: [2025 2 14 15 22 55.1534]
FrameNumber: 1
RelativeFrame: 0
TriggerIndex: 1
ans =
struct with fields:
AbsTime: [2025 2 14 15 22 55.2520]
FrameNumber: 2
RelativeFrame: 0
TriggerIndex: 2
ans =
struct with fields:
AbsTime: [2025 2 14 15 22 55.4438]
FrameNumber: 3
RelativeFrame: 1
TriggerIndex: 3
% Here is events.Type-----------------------------------------------
ans =
'Start'
ans =
'Trigger'
ans =
'Trigger'
ans =
'Trigger'
ans =
'Stop'
Type =
'Start'

2 Comments

Please attach your data file and the code you are using to import it.
It is hard to provide a solution specific to your use case without having your data.
Hi Chris, Its actually from an IMAQ video object.
vid=app.vidobj1;
start(vid)
%....wait a few sconds
stop(vid);
bool=isrunning(vid);
switch bool
case 1
ReportMessage(app,'Vid Obj RUNNING');
case 0
ReportMessage(app,'Vid Obj STOPPED');
end
% Testing event log
clc;
events = vid.EventLog
events.Data
events.Type

Sign in to comment.

 Accepted Answer

A struct array similar to your variable events:
tmp = num2cell([2025 2 14 15 22 54.8366; 2025 2 14 15 22 55.0519; 2025 2 14 15 22 55.1534; 2025 2 14 15 22 55.2520; 2025 2 14 15 22 55.4438],2).';
events = struct( ...
'Type',{'Start','Trigger','Trigger','Trigger','Stop'}, ...
'Data',num2cell(struct('AbsTime',tmp,'FrameNumber',{0,0,1,2,3},'RelativeFrame',{0,0,0,0,1},'TriggerIndex',{0,0,1,2,3})))
events = 1x5 struct array with fields:
Type Data
events(1), events(1).Data
ans = struct with fields:
Type: 'Start' Data: [1x1 struct]
ans = struct with fields:
AbsTime: [2025 2 14 15 22 54.8366] FrameNumber: 0 RelativeFrame: 0 TriggerIndex: 0
events(end), events(end).Data
ans = struct with fields:
Type: 'Stop' Data: [1x1 struct]
ans = struct with fields:
AbsTime: [2025 2 14 15 22 55.4438] FrameNumber: 3 RelativeFrame: 1 TriggerIndex: 3
One way to build something like the table you're trying to build:
Type = {events.Type}.'
Type = 5x1 cell array
{'Start' } {'Trigger'} {'Trigger'} {'Trigger'} {'Stop' }
Data = [events.Data]
Data = 1x5 struct array with fields:
AbsTime FrameNumber RelativeFrame TriggerIndex
AbsTime = datetime(vertcat(Data.AbsTime))
AbsTime = 5x1 datetime array
14-Feb-2025 15:22:54 14-Feb-2025 15:22:55 14-Feb-2025 15:22:55 14-Feb-2025 15:22:55 14-Feb-2025 15:22:55
% T0 = datetime(events(1).Data.AbsTime)
T0 = AbsTime(1) % same
T0 = datetime
14-Feb-2025 15:22:54
DT = AbsTime-T0
DT = 5x1 duration array
00:00:00 00:00:00 00:00:00 00:00:00 00:00:00
DT.Format = 'mm:ss.SSSS'
DT = 5x1 duration array
00:00.0000 00:00.2153 00:00.3167 00:00.4154 00:00.6072
count = (1:numel(events)).';
FrameNumber = vertcat(Data.FrameNumber);
T = table(count,FrameNumber,DT,Type)
T = 5x4 table
count FrameNumber DT Type _____ ___________ __________ ___________ 1 0 00:00.0000 {'Start' } 2 0 00:00.2153 {'Trigger'} 3 1 00:00.3167 {'Trigger'} 4 2 00:00.4154 {'Trigger'} 5 3 00:00.6072 {'Stop' }

10 Comments

Thats works, thankyou.
Is there any reason why in my command window its not aligned up like your:
You're welcome! Please remember to "Accept" this answer. Thanks!
I'm not sure why the table is misaligned in your command window. It looks ok for me wherever I run it (here, desktop, MATLAB online, live script).
@Jason: it looks like you are using a variable-width font. If you want text in the command window to align then use a monospaced font.

Thats a great catch! I did change my font to "Dialog".

Thankyou very much

Could I ask one follow on question please.
If I have the creation of the table in a loop and wanted to access any one of them after the loop, is there a way to do this i.e. create some strucure / array or nested table to dump each table in?
TableData=[];
for i=1:100
%get data for table
T = table(count,FrameNumber,DT,Type) % then create table
%??? How to add table to some structure/array or neseted table?
TableData(i)=T ?
end
thanks
Yes, you can use a cell array, e.g.:
i_max = 100;
TableData = cell(1,i_max); % pre-allocate cell array
for i = 1:i_max
% get data for table
TableData{i} = table(count,FrameNumber,DT,Type); % store table in cell array
end
Sorry, last question. I also want to create a column with the difference time from the previous one (DiffDT). But its length is one short so won't add to the table
function [T,count]=EventsLogTable(app,vid)
events = vid.EventLog;
% events.Data
% events.Type
Type = {events.Type}.';
Data = [events.Data];
AbsTime = datetime(vertcat(Data.AbsTime));
T0 = AbsTime(1); % same
DT = milliseconds(AbsTime-T0);
DiffDT=diff(DT) % ***************** NEW LINE
%DT.Format = 'mm:ss.SSSS'; % 'mm:ss.SSSS';
count = (1:numel(events)).';
FrameNumber = vertcat(Data.FrameNumber);
T = table(count,FrameNumber,DT,DiffDT,Type);
end
Is it a matter of just padding a zero to the start, or is there a more elegant way?
DiffDT=[0;DiffDT]

Yes, I would pad a zero or NaN to the start of DiffDT, as you suggest.

Sign in to comment.

More Answers (0)

Products

Release

R2023b

Tags

Asked:

on 14 Feb 2025

Commented:

on 15 Feb 2025

Community Treasure Hunt

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

Start Hunting!