-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbag2mat.m
179 lines (165 loc) · 6.4 KB
/
bag2mat.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
function [Vid,VidTime,FlyState,AI,FILES] = bag2mat(varargin)
%% bag2mat: Parses file name data and returns tables with relevant information: saves in .mat file
% INPUTS:
% root : varargin=root , root directory containg .bag files >>> files will be saved in a folder titled "mat"
% inside this directory. If no input is given, will default to current folder.
% OUTPUTS:
% Vid : raw video data
% VidTime : normalized video time
% FlyState : fly kinematic data
% AI : analog input voltages
% FILES : filename listing
%---------------------------------------------------------------------------------------------------------------------------------
% USAGE:
% [] = bag2mat()
% - opens dialog window to select files in current folder
% [] = bag2mat(root)
% - opens dialog window to select files in user defined root folder
% [] = bag2mat(root,'kinefly')
% - for kinefly export RGB video
%---------------------------------------------------------------------------------------------------------------------------------
% root = 'C:\Users\boc5244\Box Sync\Research\bags\TEST';
%---------------------------------------------------------------------------------------------------------------------------------
% Allow user to set root directory & set video type
version = 0; % default is raw video
if nargin==0
root = '';
elseif nargin==1
root = varargin{1};
elseif nargin==2
root = varargin{1};
if strcmp(varargin{2},'raw')
version = 0;
elseif strcmp(varargin{2},'kinefly')
version = 1;
else
error('2nd input must be ''raw'' or ''kinefly''')
end
elseif nargin>2
error('Too many inputs')
else
error('DEBUG')
end
% Set directory & get files
[FILES, PATH] = uigetfile({'*.bag', 'BAG-files'}, 'Select .bag files', root, 'MultiSelect','on');
FILES = cellstr(FILES)'; % if only one file, store in cell
n.Files = length(FILES); % # of .bag files to parse
% Set output directory to store .mat files
matdir = [PATH 'mat']; % export directory to save .mat files
[status,msg,~] = mkdir(matdir); % create directory for .mat files
if status
warning(msg)
disp(['Folder located: ' matdir])
else
error('Directory not created')
end
% Topic information: [video , flystate, analog in]
if version
TopicList = {'/kinefly/image_output','/kinefly/flystate','/stimulus/ai'}';
else
TopicList = {'/camera/image_raw','/kinefly/flystate','/stimulus/ai'}';
end
TopicType = {'CompressedImage','struct','struct'}';
n.Topic = length(TopicList); % # of topics in .bag files
W = waitbar(0/n.Files,'Saving data...');
tic
for kk = 1:n.Files
clear Vid VidTime FlyState AI Time Msg Topic Bag syncTime
% Get topics, messages, & time
Bag = rosbag([PATH FILES{kk}]); % load bag
Msg = cell(1,n.Topic); % messages for each topic
Time = cell(1,n.Topic); % time for flystate & AI
for jj = 1:n.Topic
Topic = select(Bag, 'Topic', TopicList{jj}); % get topics
Msg{jj} = readMessages(Topic,'DataFormat',TopicType{jj}); % get messages
Time{jj} = table2array(Topic.MessageList(:,1)); % get raw time
end
% Initialize variables
n.Frame = length(Msg{1}); % # of video frames
n.FState = length(Msg{2}); % # of fly states
FlyState = nan(n.FState,6); % fly state cell (header: time,head,LW,RW)
if ~isempty(Msg{3})
n.AState = length(Msg{3}); % # of AI states
n.ACh = length(Msg{3}{1}.Channels); % # of AI channels
AI = nan(n.AState,n.ACh+1); % AI channel cell (header: time,ch0,ch1,ch2)
end
if ~isempty(Msg{1})
InitFrame = readImage(Msg{1}{1}); % first video frame
[n.PixelY,n.PixelX,n.bit] = size(InitFrame); % size of first video frame
Vid = uint8(nan(n.PixelY,n.PixelX,n.bit,n.Frame)); % video cell
% Sync times
syncTime = Time{1}(1); % sync times to vid frame
VidTime(:,1) = Time{1} - syncTime; % video time
else
Vid = [];
VidTime = [];
% Sync times
syncTime = Time{2}(1); % sync times to vid frame
end
FlyState(:,1) = Time{2} - syncTime; % flystate time
if ~isempty(Msg{3})
AI(:,1) = Time{3} - syncTime; % AI time
end
if ~isempty(Msg{3})
maxI = max([n.AState,n.Frame,n.FState]);
else
maxI = max([n.Frame,n.FState]);
end
% Store messages in cells
for jj = 1:maxI % cycle through states
if ~isempty(Msg{3})
if jj<=n.AState
AI(jj,2:n.ACh+1) = Msg{3}{jj}.Voltages; % AI voltage
end
end
if jj<=n.Frame
Vid(:,:,:,jj) = readImage(Msg{1}{jj}); % video frame
end
if jj<=n.FState
if ~isempty(Msg{2}{jj}.Head.Angles)
FlyState(jj,2) = Msg{2}{jj}.Head.Angles; % left wing angle
end
if ~isempty(Msg{2}{jj}.Left.Angles)
FlyState(jj,3) = Msg{2}{jj}.Left.Angles; % right wing angle
end
if ~isempty(Msg{2}{jj}.Right.Angles)
FlyState(jj,4) = Msg{2}{jj}.Right.Angles; % head angle
end
if ~isempty(Msg{2}{jj}.Abdomen.Angles)
FlyState(jj,5) = Msg{2}{jj}.Abdomen.Angles; % abdomen angle
end
if ~isempty(Msg{2}{jj}.Aux.Freq)
FlyState(jj,6) = Msg{2}{jj}.Aux.Freq; % WBF
end
end
end
% Put data in tables
FlyState = splitvars(table(FlyState));
FlyState.Properties.VariableNames = {'Time','Head','LWing','RWing','Abdomen','WBF'}; % fly state variables
if ~isempty(Msg{3})
AI = splitvars(table(AI));
chList = cell(n.ACh+1,1);
chList{1} = 'Time';
for jj = 1:n.ACh
chList{jj+1} = ['Ch' num2str(jj-1)];
end
AI.Properties.VariableNames = chList; % AI variables
else
AI = [];
end
% Save .mat file in directory
[~,filename,~] = fileparts(FILES{kk}); % get filename
dateIdx = strfind(filename,'201'); % will work until 2020
filename = filename(1:dateIdx-2); % remove date-time at end of filename
save([PATH '\mat\' filename '.mat'] , 'Vid','VidTime','FlyState','AI','FILES','-v7.3') % save data to .mat file
waitbar(kk/n.Files,W,'Saving data...');
end
close(W)
disp('DONE')
toc
beep on
for kk = 1:5
beep
pause(0.5)
end
end