Skip to content

Commit

Permalink
Merge pull request #126 from RNA-FRETools/mapping-for-large-vid
Browse files Browse the repository at this point in the history
Add zoom function in Mapping tool
  • Loading branch information
mca-sh authored Mar 6, 2024
2 parents 0cccf41 + 3d0c59e commit 2daa963
Show file tree
Hide file tree
Showing 14 changed files with 300 additions and 151 deletions.
2 changes: 1 addition & 1 deletion MASH-FRET/.release_version.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"tag" : "1.3.3.3",
"prev_commit_hash" : "57a26cdd"
"prev_commit_hash" : "fd17e646"
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ function figure_map_CloseRequestFcn(obj, evd, h_fig)
end
end
if ~strcmp(exit_choice, 'Yes')
beadsSelect(h_fig);
return
end

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,5 @@
function figure_map_ResizeFcn(obj, evd, subImg, h_fig)
function figure_map_ResizeFcn(obj, evd, h_fig)

h = guidata(h_fig);
q = h.map;

nChan = size(q.axes_top,2);
% Draw pictures in axes
for i = 1:nChan
pos_closeUp = get(q.axes_top(i), 'Position');
pos_full = get(q.axes_bottom(i), 'Position');
x = pos_full(3);
y = pos_full(4);
X = pos_closeUp(3);
fract = 0.5*y*X/x;
ylim(q.axes_top(i), [(1-fract)*size(subImg{i},1) size(subImg{i},1)]);
end

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
function slider_map_x_Callback(obj,evd,h_fig)

updatePnts(h_fig);
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
function slider_map_y_Callback(obj, evd, h_fig)

updatePnts(h_fig);
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
function slider_zoom_Callback(obj,evd,h_fig)

h = guidata(h_fig);
q = h.map;

fact = get(obj,'Value');

% update zoom factor text
q.text_zoom.String = ['Zoom: ',num2str(round(fact*100)),'%'];

nChan = numel(q.axes_bottom);
for c = 1:nChan
img_c = get(q.axes_bottom(c), 'UserData');
[resy,resx] = size(img_c);

% calculates smallest slider step
posax = getPixPos(q.axes_top(c));
[wrect,hrect] = calcmaptoolrectdim(fact,resx,posax(3),posax(4));
[stpx,stpy] = calcmaptoolsldstep(wrect,hrect,resx,resy);

% set slider step
q.slider_x(c).SliderStep = stpx;
q.slider_y(c).SliderStep = stpy;

% recenter rectangle
x0 = q.rect(c).Position(1)+q.rect(c).Position(3)/2;
y0 = q.rect(c).Position(2)+q.rect(c).Position(4)/2;
xrect = x0-wrect/2;
xrect(xrect<0) = 0;
xrect(xrect>(resx-wrect)) = resx-wrect;
yrect = y0-hrect/2;
yrect(yrect<0) = 0;
yrect(yrect>(resy-hrect)) = resy-hrect;

% adjust slider positions accordingly
xc = xrect/(resx-wrect);
xc(isnan(xc) || isinf(xc)) = 0;
yc = 1-yrect/(resy-hrect);
yc(isnan(yc) || isinf(yc)) = 0;
q.slider_x(c).Value = xc;
q.slider_y(c).Value = yc;
end

updatePnts(h_fig)
Original file line number Diff line number Diff line change
@@ -1,124 +1,158 @@
function buildMappingTool(img, lim, h_fig)
% buildMappingTool(img, lim, h_fig)
%
% Build "Mapping tool" window accessed by clicking "Map" in panel "Molecule
% coordinates" of Video processing.
%
% img: {1-by-1}[resy-by-resx] average image of a multi-channel video, or
% {1-by-nChan}[resy_c-by-resx_c] average image of single-channel
% videos.
% lim: empty, or [1-by-(nChan+1)] pixel limits of channels on multi-channel
% video.
% h_fig: handle to main figure

% defaults
un = 'pixels';
hsld = 20;
wsldy = 20;
htxt = 14;
winratio = 0.75;
zoomsldratio = 0.3;
stpbig = 1/4;
stpzoomsmall = 1/20;
zoomfactmax = 5;
figttl = 'Mapping tool';
menulbl0 = 'Delete last point';
menulbl1 = 'Delete last set';
menulbl2 = 'Export to file...';
menulbl3 = 'Close and Save';
menulbl4 = 'Help';
strzoom = 'Zoom: 100%';

% collect interface parameters
h = guidata(h_fig);

% determine number of channels
multichanvid = numel(img)==1 & ~isempty(lim);

% Size parameters
hWin = 0.75;
wWin = 0.75;
xWin = (1-wWin)/2;
yWin = (1-hWin)/2;
w_sld = 0.015;

if multichanvid
nChan = size(lim,2) - 1;
else
nChan = numel(img);
end
subImg = cell(1,nChan);
A_w = zeros(1,nChan);

% size parameters
pos0 = get(0,'screensize');
hWin = pos0(4)*winratio;
wWin = pos0(3)*winratio;
xWin = (pos0(3)-wWin)/2;
yWin = (pos0(4)-hWin)/2;
wtxt = zoomsldratio*wWin;
hax = (hWin-htxt-2*hsld)/2;
wax = zeros(1,nChan);
for c = 1:nChan
if multichanvid
subImg{c} = img{1}(:,lim(c)+1:lim(c+1));
A_w(c) = lim(c+1) - lim(c);
wax(c) = lim(c+1)-lim(c);
else
subImg{c} = img{c};
A_w(c) = size(img{c},2);
wax(c) = size(img{c},2);
end
end
A_w = A_w/sum(A_w);
subA_w = A_w*(1 - nChan*w_sld);
A_h = 0.5;
wax = (wWin-nChan*wsldy)*wax/sum(wax);

if multichanvid
res_y = repmat(size(img{1},1),[1,nChan]);
else
res_y = zeros(1,nChan);
for c =1:nChan
res_y(c) = size(img{c},1);
% collects channel average images and dimensions
img_c = cell(1,nChan);
res_y = zeros(1,nChan);
res_x = zeros(1,nChan);
stphor = zeros(nChan,2);
stpver = zeros(nChan,2);
for c = 1:nChan
if multichanvid
img_c{c} = img{1}(:,lim(c)+1:lim(c+1));
else
img_c{c} = img{c};
end
res_y(c) = size(img_c{c},1);
res_x(c) = size(img_c{c},2);

% calculates smallest slider step
[wrect,hrect] = calcmaptoolrectdim(1,res_x(c),wax(c),hax);
[stphor(c,:),stpver(c,:)] = ...
calcmaptoolsldstep(wrect,hrect,res_x(c),res_y(c));
end

% create figure
h.figure_map = figure('Units', 'normalized', 'Name', 'Mapping tool', ...
'Position', [xWin yWin wWin hWin], 'Toolbar', 'none', 'MenuBar', ...
'none', 'NumberTitle', 'off', 'Pointer', 'crosshair');
h.figure_map = figure('Units', un, 'Name', figttl, 'Position', ...
[xWin yWin wWin hWin], 'Toolbar', 'none', 'MenuBar', 'none', ...
'NumberTitle', 'off', 'Pointer', 'crosshair');
h_fig2 = h.figure_map;
set(h_fig2,'ResizeFcn',{@figure_map_ResizeFcn, subImg, h_fig},...
'CloseRequestFcn',{@figure_map_CloseRequestFcn,h_fig});
set(h_fig2,'CloseRequestFcn',{@figure_map_CloseRequestFcn,h_fig});

% initialize mapping tool's structure
q = struct;

% build menus
q.menu = uimenu('Label','Menu');
q.menuDelLast = uimenu(q.menu, 'Label', 'Delete last point', 'Callback', ...
q.menuDelLast = uimenu(q.menu, 'Label', menulbl0, 'Callback', ...
{@deletePnt, 'last', h_fig});
q.menuDelSet = uimenu(q.menu, 'Label', 'Delete last set', 'Callback', ...
q.menuDelSet = uimenu(q.menu, 'Label', menulbl1, 'Callback', ...
{@deletePnt, 'set', h_fig});
q.menuExport = uimenu(q.menu, 'Label', 'Export to file...', 'Callback', ...
q.menuExport = uimenu(q.menu, 'Label', menulbl2, 'Callback', ...
{@menu_map_export, h_fig});
q.menuClose = uimenu(q.menu, 'Label', 'Close and Save', 'Callback', ...
q.menuClose = uimenu(q.menu, 'Label', menulbl3, 'Callback', ...
{@figure_map_CloseRequestFcn, h_fig});
q.menu_help = uimenu('Label', 'Help', 'Callback',...
q.menu_help = uimenu('Label', menulbl4, 'Callback',...
{@pushbutton_help_Callback,getDocLink('mapping tool')});

% build GUI
yNext = 0;
xNext = 0;
x = 0;
y = 0;
for c = 1:nChan
q.axes_bottom(c) = axes('Units', 'normalized', 'Position', ...
[xNext yNext A_w(c) A_h]);
q.axes_bottom(c) = axes('Units', un, 'Position', [x y wax(c) hax], ...
'UserData', img_c{c}, 'NextPlot', 'replacechildren', 'YDir', ...
'reverse');

xNext = xNext + A_w(c);
x = x + wax(c);
end

yNext = A_h;
xNext = 0;

y = hax;
x = 0;
for c = 1:nChan
q.axes_top(c) = axes('Units', 'normalized', 'Position', ...
[xNext yNext subA_w(c) A_h]);

xNext = xNext + subA_w(c);
q.axes_top(c) = axes('Units', un, 'Position', [x y wax(c) hax], ...
'NextPlot', 'replacechildren', 'YDir', 'reverse');

q.slider(c) = uicontrol('Style','slider','Units','normalized',...
'Position',[xNext yNext w_sld A_h],'Min',0,'Max',1,'Value',0,...
'SliderStep',[1/res_y(c) 0.25],'Callback',...
{@slider_map_Callback,h_fig,c});
x = x + wax(c);
q.slider_y(c) = uicontrol('Style', 'slider', 'Units', un, 'Position', ...
[x y wsldy hax], 'Min', 0, 'Max', 1, 'Value', 0, 'SliderStep', ...
stpver(c,:), 'Callback', {@slider_map_y_Callback, h_fig});

xNext = xNext + w_sld;
x = x + wsldy;
end

% Draw pictures in axes
for c = 1:nChan
imagesc(subImg{c}, 'Parent', q.axes_bottom(c));
set(q.axes_bottom(c), 'UserData', subImg{c});
axis(q.axes_bottom(c), 'image');

q.img(c) = imagesc(0.5:size(subImg,2)-0.5, 0.5:size(subImg,1)-0.5, ...
subImg{c}, 'Parent', q.axes_top(c));
set(q.img(c), 'ButtonDownFcn', {@axes_map_ButtonDownFcn, h_fig, c});
pos_closeUp = get(q.axes_top(c), 'Position');
pos_full = get(q.axes_bottom(c), 'Position');
W = pos_full(3);
H = pos_full(4);
w = pos_closeUp(3);
hg = 0.5*(H/W)*w;
xlim(q.axes_top(c), [0 size(subImg,2)]);
ylim(q.axes_top(c), [(1-hg)*size(subImg{c},1) size(subImg{c},1)]);

q.rect(c) = rectangle('Parent', q.axes_bottom(c), 'Position', ...
[2, (1-hg)*size(subImg{c},1)+2, size(subImg{c},2)-2, ...
hg*size(subImg{c},1)-2], 'LineWidth', 2, 'EdgeColor', 'r');
y = 2*hax;
x = 0;
for c = 1:nChan
q.slider_x(c) = uicontrol('Style', 'slider', 'Units', un, 'Position', ...
[x y wax(c) hsld], 'Min', 0, 'Max', 1, 'Value', 0, 'SliderStep', ...
stphor(c,:), 'Callback', {@slider_map_x_Callback, h_fig});

set(q.slider(c), 'SliderStep', [0.1 0.25]);
x = x + wax(c) + wsldy;
end

y = y+hsld;
x = (wWin-wtxt)/2;
q.text_zoom = uicontrol('style', 'text', 'units', un, 'position', ...
[x y wtxt htxt], 'string', strzoom, 'horizontalalignment', 'center');

y = y+htxt;
q.slider_zoom = uicontrol('Style', 'slider', 'Units', un, 'Position', ...
[x y wtxt hsld], 'Min', 1, 'Max', zoomfactmax, 'Value', 1, ...
'SliderStep', [stpzoomsmall stpbig], 'Callback', ...
{@slider_zoom_Callback, h_fig});


colormap(h_fig2,'turbo');

h.map = q;
guidata(h_fig2,q);
guidata(h_fig,h);

setProp(h_fig2,'units','normalized');
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
function [wrect,hrect] = calcmaptoolrectdim(z,resx,wax,hax)

wrect = resx/z;
hrect = wrect*hax/wax;
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
function [stpx,stpy] = calcmaptoolsldstep(wrect,hrect,resx,resy)

stpx = [wrect/(4*resx),wrect/resx];
stpx(isnan(stpx) | isinf(stpx)) = 0;
stpy = [hrect/(4*resy),hrect/resy];
stpy(isnan(stpy) | isinf(stpy)) = 0;
Loading

0 comments on commit 2daa963

Please sign in to comment.