how to slice a 3d array with slider?

10 visualizzazioni (ultimi 30 giorni)
Rabih Sokhen
Rabih Sokhen il 19 Giu 2022
Commentato: Voss il 19 Giu 2022
Code:
clear all
clc
y=randn(10,10,10);
h = uicontrol('style','slider','Min',0,'Max',100,'Value',0.01, 'callback',@(src,evt)disp(get(src,'value')));
a=ceil(h.Value)
pcolor(y(:,:,a))
% i would like to move the slider along the z direction and slice my "y" at the exact position where my slider stops.
can someone help me plz
thank you in advance

Risposta accettata

Voss
Voss il 19 Giu 2022
Modificato: Voss il 19 Giu 2022
Here's one way to do that:
clear all
clc
y = randn(10,10,10);
N = size(y,3);
h = uicontrol( ...
'style','slider', ...
'Min',1, ...
'Max',N, ...
'Value',1, ...
'SliderStep',[1 3]/(N-1), ...
'Units','normalized', ...
'Position',[0 0 1 0.06], ...
'callback',{@cb_slice,y});
cb_slice(h,[],y); % initialize the plot
function cb_slice(src,evt,y)
pcolor(y(:,:,round(src.Value)));
end
  3 Commenti
Rik
Rik il 19 Giu 2022
For general advice and examples for how to create a GUI (and avoid using GUIDE), have look at this thread. You will find the advice to use explicit handles.
Voss
Voss il 19 Giu 2022
@Rabih Sokhen: Notice how the slider's Callback is specified to have y as an input argument:
'callback',{@cb_slice,y}
That is done so that cb_slice has access to the variable y.
If you want cb_slice to operate on two arrays, then you can send both of them as input arguments:
'callback',{@cb_slice,y,u}
and change the definition of cb_slice to include u, and also include both calls to pcolor and both calls to subplot in there:
function cb_slice(src,evt,y,u)
subplot(121)
pcolor(y(:,:,round(src.Value)));
subplot(122)
pcolor(u(:,:,round(src.Value)));
end
and initialize the plots by calling cb_slice once with both arrays when the program starts:
cb_slice(h,[],y,u); % initialize the plots
[ Note that if the size of y and the size of u in their third dimension are not the same, then you'll have some problems. Specifically, if size(u,3) > size(y,3), then you won't be able to see the slices of u beyond size(y,3), and if size(u,3) < size(y,3), then you'll get an error trying to access slices of u that don't exist when the slider Value is greater than size(u,3). ]
Now, the slider callback is creating new pcolor surfaces in each subplot each time it is called, which is inefficient. A better way would be to create the pcolor surfaces once when the program starts, and have the slider Callback merely update them rather than creating new ones:
clear all
clc
y = randn(10,10,10);
u = randn(10,10,10);
N = size(y,3);
% create the pcolor surfaces
subplot(121)
p(1) = pcolor(y(:,:,1));
subplot(122)
p(2) = pcolor(u(:,:,1));
h = uicontrol( ...
'style','slider', ...
'Min',1, ...
'Max',N, ...
'Value',1, ...
'SliderStep',[1 3]/(N-1), ...
'Units','normalized', ...
'Position',[0 0 1 0.06], ...
'callback',{@cb_slice,p,y,u});
cb_slice(h,[],p,y,u); % initialize the plots
function cb_slice(src,evt,p,y,u)
val = round(src.Value);
p(1).CData = y(:,:,val);
p(2).CData = u(:,:,val);
end
As you can see there, now cb_slice has another additional input argument, p, which is an array of surfaces created by pcolor.
At this point, it's worth pointing out another approach: rather than passing everything you need as input arguments to the callback function(s), you can make cb_slice a nested function:
function pcolor_slider_test()
clc
y = randn(10,10,10);
u = randn(10,10,10);
N = size(y,3);
% create the pcolor surfaces
subplot(121)
p(1) = pcolor(y(:,:,1));
subplot(122)
p(2) = pcolor(u(:,:,1));
h = uicontrol( ...
'style','slider', ...
'Min',1, ...
'Max',N, ...
'Value',1, ...
'SliderStep',[1 3]/(N-1), ...
'Units','normalized', ...
'Position',[0 0 1 0.06], ...
'callback',@cb_slice);
cb_slice(); % initialize the plots
function cb_slice(~,~)
val = round(h.Value);
p(1).CData = y(:,:,val);
p(2).CData = u(:,:,val);
end
end
Now p, y, and u don't have to be passed in to cb_slice because cb_slice is nested under the main function (which I call pcolor_slider_test), which means that the code inside cb_slice "sees" the variables in pcolor_slider_test's workspace, so they don't have to be given as input arguments. Using nested functions makes the code cleaner, in my opinion, and it's the approach I would probably use if I were doing this myself.

Accedi per commentare.

Più risposte (0)

Categorie

Scopri di più su Graphics Object Programming in Help Center e File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by