Skip to content

Commit 56045cb

Browse files
committed
v0.1.8
[v0.1.8, 7/24/2018] GUI "Replay" window: Added "[G]oto frame" keyboard shortcut. Added fast frame jump by pressing "Shift" + Left/Right keys. Debugged "vistrack update" command. Uploaded sample files (R12A2*). Removed dependencies for "Statistics and Machine Learning" toolbox. Only "Image processing toolbox" is required. "Parallel processing toolbox" is optional for faster processing. GUI "Initialize" button caches previous answers and a movie clip. New command added: "vistrack download-sample" Download a sample video file that is too large to host from Github.com
1 parent 0f3d3d1 commit 56045cb

16 files changed

+638
-87
lines changed

GUI.fig

212 Bytes
Binary file not shown.

GUI.m

Lines changed: 87 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
% Edit the above text to modify the response to help GUI
2424

25-
% Last Modified by GUIDE v2.5 23-Jul-2018 16:44:51
25+
% Last Modified by GUIDE v2.5 24-Jul-2018 11:57:00
2626

2727
% Begin initialization code - DO NOT EDIT
2828
gui_Singleton = 1;
@@ -62,10 +62,7 @@ function GUI_OpeningFcn(hObject, eventdata, handles, varargin)
6262

6363
[vcVer, vcVer_date] = version_();
6464
set(handles.textVer, 'String', sprintf('%s (%s) James Jun', vcVer, vcVer_date));
65-
66-
if ~exist('.git', 'dir') ~= 7
67-
set(handles.btnUpdate, 'Enable', 'off');
68-
end
65+
set(handles.btnUpdate, 'Enable', ifeq_(exist_dir_('.git'), 'on', 'off'));
6966

7067
% Update handles structure
7168
guidata(hObject, handles);
@@ -133,6 +130,7 @@ function btnLoadVideo_Callback(hObject, eventdata, handles)
133130
end
134131
handles.vidFname = vidFname;
135132
buttons_off_(handles);
133+
clear_cache_();
136134

137135
% Set result field
138136
vcFile_out = subsFileExt_(vidFname, '_Track.mat');
@@ -158,7 +156,7 @@ function btnLoadVideo_Callback(hObject, eventdata, handles)
158156

159157
try
160158
set(handles.edit1, 'String', handles.vidFname);
161-
h = msgbox('Loading... (this will close automatically)');
159+
h = msgbox('Loading... (this will close automatically)', 'modal');
162160
% handles.vidobj = VideoReader(handles.vidFname);
163161
handles.vidobj = vistrack('VideoReader', vidFname);
164162
fprintf('Video file info: %s\n', handles.vidFname);
@@ -535,35 +533,11 @@ function btnPreview_Callback(hObject, eventdata, handles)
535533
[WINPOS, ~] = getBoundingBoxPos(handles.xy_init, size(img0), winlen*[1 1]);
536534
img = handles.img1(WINPOS(3):WINPOS(4), WINPOS(1):WINPOS(2), :);
537535
img0c = img0(WINPOS(3):WINPOS(4), WINPOS(1):WINPOS(2), :);
538-
% img00c = handles.img00(WINPOS(3):WINPOS(4), WINPOS(1):WINPOS(2));
539-
540-
% dimg = uint8(img0c - img);
541536
dimg = uint8_diff(img0c, img, 0);
542-
% dimg = uint8(mean(single(img0c) - single(img),3));
543-
% dimg = uint8(sum(img0c - img, 3));
544-
% dimg = uint8(mean(single(img) - single(img0c), 3)/3);
545-
% dimg = uint8(abs(mean(single(img0c) - single(img), 3)/3));
546-
547-
% absimg = imabsdiff(handles.img00, handles.img1);
548-
% absimg(~handles.MASK) = 0;
549-
% absimg = absimg(WINPOS(3):WINPOS(4), WINPOS(1):WINPOS(2));
550-
% figure; subplot 121; imagesc(absimg); title('absdiff');
551-
% subplot 122; imagesc(dimg); title('diff');
552-
% return;
553-
554537
BW = imdilate(bwmorph((dimg > IM_THRESH), 'clean', inf), SE);
555538
BW = imfill(BW, 'holes');
556539
BW = imclearborder(BW);
557540

558-
% dimg1 = dimg;
559-
% dimg1(bwperim(BW)) = 256;
560-
% imgabs = im(handles.img00, handles.img1);
561-
% imgabs(~handles.MASK) = 0;
562-
% figure; imagesc(imgabs);
563-
% figure; imagesc(dimg1);
564-
% return;
565-
566-
% [BW, AreaTarget] = bwgetlargestblob(BW);
567541
regions = regionprops(BW, {'Area', 'Centroid', 'Orientation', 'FilledImage', 'BoundingBox'});
568542
if numel(regions)>1
569543
L = bwlabel(BW, 8);
@@ -610,7 +584,7 @@ function btnPreview_Callback(hObject, eventdata, handles)
610584
imagesc(img4, INTENSITY_LIM);
611585
axis equal; axis tight;
612586
set(gca, {'XTick', 'YTick'}, {[],[]});
613-
title('4. Superimposed');
587+
title_('4. Superimposed (if incorrect, lower "IM_THRESH")');
614588
colormap gray;
615589

616590

@@ -861,7 +835,7 @@ function btnMovOut_Callback(hObject, eventdata, handles)
861835
%colorbar
862836
plotColorbar(size(handles.img0), vrRateSrt, vrQuantSrt);
863837
EODR1 = EODR(TEOD > TLIM(1) & TEOD < TLIM(2));
864-
RLIM = [quantile(EODR1, .001), quantile(EODR1, .999)];
838+
RLIM = [quantile_(EODR1, .001), quantile_(EODR1, .999)];
865839
htext = [];
866840
vhChevron = [];
867841
for iframe=1:nframes
@@ -1156,7 +1130,7 @@ function btnReplay_Callback(hObject, eventdata, handles)
11561130
%setup fig
11571131
timer1 = timer('Period', 1/15, 'ExecutionMode', 'fixedRate', 'TasksToExecute', inf);
11581132
hFig = figure('NumberTitle', 'off', 'Name', ...
1159-
'[H]elp; [L/R/U/D]; SPACEBAR:Pause; [F]lip; [C]ut upto here');
1133+
'[H]elp; (Sft)+[L/R/U/D]; SPACEBAR:Pause; [F]lip; [C]ut upto here; [G]oto Frame');
11601134
hImg = imshow(imadjust(MOV(:,:,1))); hold on;
11611135
iFrame = 1;
11621136
XC = mrXC(iFrame,:);
@@ -1292,7 +1266,7 @@ function btnUpdate_Callback(hObject, eventdata, handles)
12921266
% eventdata reserved - to be defined in a future version of MATLAB
12931267
% handles structure with handles and user data (see GUIDATA)
12941268
vistrack('update');
1295-
msgbox('Update successful, please restart');
1269+
msgbox('Update successful, Restart the app');
12961270

12971271

12981272
%--------------------------------------------------------------------------
@@ -1396,11 +1370,12 @@ function btnListFiles_Callback(hObject, eventdata, handles)
13961370
end
13971371

13981372

1399-
% --- Executes on button press in pushbutton65.
1400-
function pushbutton65_Callback(hObject, eventdata, handles)
1401-
% hObject handle to pushbutton65 (see GCBO)
1373+
% --- Executes on button press in btnBarPlots.
1374+
function btnBarPlots_Callback(hObject, eventdata, handles)
1375+
% hObject handle to btnBarPlots (see GCBO)
14021376
% eventdata reserved - to be defined in a future version of MATLAB
14031377
% handles structure with handles and user data (see GUIDATA)
1378+
vistrack('trialset-barplots', get_str_(handles.editTrialSet));
14041379

14051380

14061381
% --- Executes on button press in pushbutton66.
@@ -1439,7 +1414,13 @@ function pushbutton70_Callback(hObject, eventdata, handles)
14391414

14401415

14411416
function [FLIM, TC, img1, img00] = mov_flim_(vidobj, nFrames_load)
1417+
% mov_flim_(): clear cache
1418+
1419+
persistent csAns1 csAns2 csAns3 mov1
1420+
if nargin==0, [csAns1, csAns2, csAns3] = deal([]); return; end %clear cache
1421+
14421422
if nargin<2, nFrames_load = 300; end % skip every 10 frames
1423+
14431424
% if isempty(nFrames_skip), nFrames_skip = 75; end
14441425
warning off;
14451426
nFrames = vidobj.NumberOfFrames;
@@ -1448,39 +1429,49 @@ function pushbutton70_Callback(hObject, eventdata, handles)
14481429
% viF = 1:nFrames_skip:nFrames;
14491430
viF = unique(round(linspace(1, nFrames, nFrames_load)));
14501431
% viF = 1:nFrames_load; % much faster to load
1451-
tmr = read_(vidobj, viF);
1432+
if isempty(mov1)
1433+
mov1 = mov_shrink_(read_(vidobj, viF), 2);
1434+
end
14521435

14531436
% rough scan
1454-
implay(tmr);
1437+
implay(mov1);
14551438
uiwait(msgbox('Find the first and last frame to track, and close the movie'));
1456-
csAns = inputdlg({'First frame', 'Last frame'}, 'Get frames', 1, ...
1457-
{'1', sprintf('%d', numel(viF))});
1439+
if isempty(csAns1), csAns1 = {'1', sprintf('%d', numel(viF))}; end
1440+
csAns = inputdlg({'First frame', 'Last frame'}, 'Get frames', 1, csAns1);
1441+
csAns1 = csAns;
14581442
frame_first = viF(str2num(csAns{1}));
14591443
frame_last = viF(str2num(csAns{2}));
1444+
fprintf('#1: First frame: %s; Last frame: %s\n', csAns{1}, csAns{2});
14601445

14611446
% Find first frame to track
14621447
viF_first = trim_(frame_first + (-150:149), 1, nFrames);
14631448
tmr = read_(vidobj, viF_first);
1464-
implay(tmr);
1449+
implay(mov_shrink_(tmr, 2));
14651450
uiwait(msgbox('Find the first frame to track and background, and close the movie'));
1466-
csAns = inputdlg({'First frame', 'Background frame'}, 'Get frames', 1, ...
1467-
{'1', num2str(numel(viF_first))});
1451+
if isempty(csAns2), csAns2 = {'1', num2str(numel(viF_first))}; end
1452+
csAns = inputdlg({'First frame', 'Background frame'}, 'Get frames', 1, csAns2);
1453+
csAns2 = csAns;
14681454
img1 = tmr(:,:,str2num(csAns{1}));
14691455
img00 = tmr(:,:,str2num(csAns{2}));
14701456
frame_first = viF_first(str2num(csAns{1}));
1457+
fprintf('#2: First frame: %s; Background frame: %s\n', csAns{1}, csAns{2});
14711458

14721459
% Find last frame to track
14731460
viF_last = trim_(frame_last + (-150:149), 1, nFrames);
14741461
tmr = read_(vidobj, viF_last);
1475-
implay(tmr);
1462+
implay(mov_shrink_(tmr, 2));
14761463
uiwait(msgbox('Find the last frame to track, and close the movie'));
1477-
csAns = inputdlg({'Last frame'}, 'Get frames', 1, ...
1478-
{'1'});
1464+
iFrame3 = ceil(numel(viF_last)/2);
1465+
if isempty(csAns3), csAns3 = {num2str(iFrame3)}; end
1466+
csAns = inputdlg({'Last frame'}, 'Get frames', 1, csAns3);
1467+
csAns3 = csAns;
14791468
frame_last = viF_last(str2num(csAns{1}));
1469+
fprintf('#3: Last frame: %s\n', csAns{1});
14801470

14811471
FLIM = [frame_first, frame_last];
14821472
TC = TC(frame_first:frame_last);
14831473

1474+
14841475
function close_(h)
14851476
try close(h); catch; end
14861477

@@ -1572,3 +1563,52 @@ function disp_cs_(cs)
15721563
P.(vcName_) = [];
15731564
end
15741565
end
1566+
1567+
1568+
%--------------------------------------------------------------------------
1569+
% 7/24/2018 JJJ: Copied from jrc3.m
1570+
function flag = exist_dir_(vcDir)
1571+
if isempty(vcDir)
1572+
flag = 0;
1573+
else
1574+
flag = exist(vcDir, 'dir') == 7;
1575+
end
1576+
1577+
1578+
%--------------------------------------------------------------------------
1579+
% 7/24/2018: Copied from jrc3.m
1580+
function flag = key_modifier_(event, vcKey)
1581+
% Check for shift, alt, ctrl press
1582+
try
1583+
flag = any(strcmpi(event.Modifier, vcKey));
1584+
catch
1585+
flag = 0;
1586+
end
1587+
1588+
1589+
%--------------------------------------------------------------------------
1590+
% 7/24/2018: Copied from jrc3.m
1591+
function out = ifeq_(if_, true_, false_)
1592+
if (if_)
1593+
out = true_;
1594+
else
1595+
out = false_;
1596+
end
1597+
1598+
1599+
%--------------------------------------------------------------------------
1600+
% 7/24/2018 JJJ: Clear persistent memories
1601+
function clear_cache_()
1602+
mov_flim_(); % clear cache;
1603+
1604+
1605+
%--------------------------------------------------------------------------
1606+
% 7/24/2018 JJJ: resize movie by a scale factor
1607+
function mov = mov_shrink_(mov, nSkip)
1608+
if nSkip==1, return; end
1609+
mov = mov(1:nSkip:end, 1:nSkip:end, :);
1610+
1611+
1612+
%--------------------------------------------------------------------------
1613+
function hTItle = title_(vc)
1614+
hTItle = title(vc, 'Interpreter', 'none');

R12A2_Rs.mat

327 KB
Binary file not shown.

R12A2_Track.mat

15 MB
Binary file not shown.

R12A2_Ts.mat

171 KB
Binary file not shown.

change_log.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,19 @@
11
Visual Tracker (vistrack) change log
22
James Jun, Maler Lab
33

4+
[v0.1.8, 7/24/2018]
5+
GUI "Replay" window:
6+
Added "[G]oto frame" keyboard shortcut.
7+
Added fast frame jump by pressing "Shift" + Left/Right keys.
8+
Debugged "vistrack update" command.
9+
Uploaded sample files (R12A2*).
10+
Removed dependencies for "Statistics and Machine Learning" toolbox.
11+
Only "Image processing toolbox" is required.
12+
"Parallel processing toolbox" is optional for faster processing.
13+
GUI "Initialize" button caches previous answers and a movie clip.
14+
New command added: "vistrack download-sample"
15+
Download a sample video file that is too large to host from Github.com
16+
417
[v0.1.7, 7/23/2018]
518
Added "Summary" button in GUI
619
Added "Export" button in GUI

default.cfg

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
pixpercm = 7.238; % run S141106_LearningCurve_Control.m first cell
2+
angXaxis = -0.946;
3+
vcFile_settings = 'settings_vistrack.m'; % default settings for vistrack GUI
4+
5+
%# Commit
6+
vcDir_commit = 'D:\Dropbox\Git\vistrack\';
7+
csFiles_commit = {'*.m', 'GUI.fig', 'change_log.txt', 'readme.txt', 'example.trialset', 'default.cfg', 'R12A2_Ts.mat', 'R12A2_Rs.mat', 'R12A2_Track.mat'};
8+
csLink_sample = {'https://www.dropbox.com/s/wamrg6ha2nk2ik3/R12A2.wmv?dl=1'}; % too large to upload via Github.com. Hosting from Dropbox instead.

detectBlink.m

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@
2626
end
2727

2828
h=msgbox('Loading... (this will close automatically)', 'detect LED blink'); drawnow;
29-
trImg = read(handles.vidobj, FLIM1);
30-
trImg = squeeze(trImg(:,:,1,:));
29+
% trImg = read(handles.vidobj, FLIM1);
30+
% trImg = squeeze(trImg(:,:,1,:));
31+
trImg = vid_read(handles.vidobj, FLIM1(1):FLIM1(2));
3132
try close(h); catch, end;
3233

3334
if isempty(xyLED), xyLED = find_mov_max_(trImg); end

keyFcnPreview.m

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,24 +13,38 @@ function keyFcnPreview(hFig, event)
1313
[iFrame, hObject] = deal(S.iFrame, S.hObject);
1414
switch lower(event.Key)
1515
case 'h' %help
16-
csHelp = {'SPACE: start and stop', 'LEFT/RIGHT: backward/forward', ...
17-
'HOME/END: start/end', 'F: Flip head/tail', ...
18-
'UP/DOWN: Speed up/down', 'C: Trim video'};
16+
csHelp = { ...
17+
'----Playback----',
18+
'[SPACE]: start and stop video',
19+
'(Shift) + LEFT/RIGHT: backward/forward (Shift: 4x)',
20+
'[UP/DOWN]: Speed up/down',
21+
'[HOME/END]: Go to start/end',
22+
'[G]oto: Go to a specific frame}',
23+
'----EDIT----',
24+
'[F]lip head/tail',
25+
'[C]ut: Trim video up to the current frame'};
1926
msgbox(csHelp);
2027

2128
case 'space' % toggle start and stop
2229
if fRunning, stop(timer1);
2330
else start(timer1); end
2431

25-
case {'leftarrow', 'rightarrow', 'f', 'home', 'end'}
32+
case {'leftarrow', 'rightarrow', 'f', 'home', 'end', 'g'}
2633
%'f' for flip, 'left' for back, 'right' for forward
2734
if fRunning, stop(timer1); end
2835
switch event.Key
29-
case 'leftarrow', S.iFrame = max(1, S.iFrame-S.REPLAY_STEP);
30-
case 'rightarrow', S.iFrame = min(nFrames, S.iFrame+S.REPLAY_STEP);
36+
case {'leftarrow', 'rightarrow'}
37+
nStep = S.REPLAY_STEP * ifeq_(key_modifier_(event, 'shift'), 4, 1);
38+
nStep = nStep * ifeq_(strcmpi(event.Key, 'leftarrow'), -1, 1);
39+
S.iFrame = min(max(1, S.iFrame + nStep), nFrames);
3140
case 'home', S.iFrame = 1;
3241
case 'end', S.iFrame = nFrames;
3342
case 'f', GUI_FLIP; %flip orientation
43+
case 'g' % go to frame
44+
S.iFrame = uigetnum(sprintf('Go to Frame (choose from 1-%d)', nFrames), S.iFrame);
45+
if isempty(S.iFrame), return; end
46+
if (S.iFrame < 1 || S.iFrame > nFrames), S.iFrame = nan; end
47+
if isnan(S.iFrame), msgbox('Cancelled'); return; end
3448
end
3549
set(S.hImg, 'CData', imadjust(handles.MOV(:,:,S.iFrame)));
3650

@@ -50,6 +64,7 @@ function keyFcnPreview(hFig, event)
5064

5165
case 'uparrow' %speed up
5266
S.REPLAY_STEP = min(S.REPLAY_STEP+1, 30);
67+
5368

5469
case 'downarrow' %speed up
5570
S.REPLAY_STEP = max(S.REPLAY_STEP-1, 1);
@@ -64,4 +79,28 @@ function keyFcnPreview(hFig, event)
6479
sprintf('F1: %d; T1: %0.3f s, Step: %d (%s)', ...
6580
S.iFrame, S.TC1(S.iFrame), S.REPLAY_STEP, vcDataID));
6681

67-
set(timer1, 'UserData', S);
82+
set(timer1, 'UserData', S);
83+
end %func
84+
85+
86+
%--------------------------------------------------------------------------
87+
% 7/24/2018: Copied from jrc3.m
88+
function flag = key_modifier_(event, vcKey)
89+
% Check for shift, alt, ctrl press
90+
try
91+
flag = any(strcmpi(event.Modifier, vcKey));
92+
catch
93+
flag = 0;
94+
end
95+
end %func
96+
97+
98+
%--------------------------------------------------------------------------
99+
% 7/24/2018: Copied from jrc3.m
100+
function out = ifeq_(if_, true_, false_)
101+
if (if_)
102+
out = true_;
103+
else
104+
out = false_;
105+
end
106+
end %func

0 commit comments

Comments
 (0)