Mathieu
Mathieu

Reputation: 5746

MATLAB uicontrol callback return matrix

Original post: MATLAB scrolling plot

I got a second part in my problem now. As before, I have a 19*1000*134 matrix that I'm plotting thanks to the nicely answer from Aero Engy on the last post.

I would like to create in my workspace a vector called clean that will have a 134 length.

By default, the value for clean(i) (with i between 1 and 134) will be 1 -- but, if I press a button on the UI interface, the value must get to 0.

My code bellow, just don't give me any ouput. The button seems to work, but when I close the figure, I don't get the vector clean.

function cleanData(data);
% data = rand(19,1000,134);
global clean
clean = ones(1,size(data,3));
f = figure('Units','Normalized','Position',[0.25 0.25 0.5 0.5]);
a =   axes('Units','Normalized','Position',[0.05 0.15, 0.75 0.75]);
s =   uicontrol(f, 'Style','Slider', 'Units','Normalized','Position',[0.05 0.025, 0.75 0.05],...
                   'Min',1,'Max',size(data,3),'Value',1, 'Callback',{@sliderChange,a});
l =   uicontrol(f, 'Style','listbox','Units','Normalized','Position',[0.85 0.15, 0.1, 0.75],...
                   'String',cellstr(num2str([1:size(data,1)]')),'Callback',{@changeChannel,a,s,data});
c = uicontrol(f, 'Style','pushbutton','Units','Normalized','String','Not clean',...
                   'Position',[0.85 0.025 0.1 0.05],'Callback',{@notClean,clean,s});

stepSize = 1/(s.Max - s.Min);
s.SliderStep = [stepSize 2*stepSize];               
changeChannel(l,[],a,s,data)

function changeChannel(l,evtData,a,s,data)
cla(a);
chanNum = str2double(l.String{l.Value});
sR = 500;  %500Hz
tempData = reshape(data(chanNum,:,:),[],size(data,3)); %Reshape each epoch into a column
tempTime = [0:1/sR:(size(data,2)-1)/sR]' + (0:1:size(data,3)-1)*2; %Build time array
plot(a,tempTime,tempData) %plot all the lines
s.Value = 1; %Rest Slider Position

function sliderChange(s,evtData,a)
viewI = round(s.Value);
disp(['Current Epoch: ' num2str(viewI)]) %console print
xlim(a,[(viewI-1)*2 viewI*2] + [-.1 .1])

function notClean(c,evtData,clean,s)
num = round(s.Value);
clean(num) = 0;
disp(['Epoch ' num2str(num) ' not clean']) %console print

What am I doing wrong ?

Bonus: It would be nice if

Thanks for the help, I'm quite new at MATLAB, and even if I improve quickly, I'm far from fully understanding this code.

Upvotes: 0

Views: 159

Answers (2)

Aero Engy
Aero Engy

Reputation: 3608

In the notClean callback I called clean out as a global. I also removed it as an input ... since it is a global it is not necessary to pass it in.

Also I added the code to advance the slider 1 each time you pressed the button.

In your workspace after closing the GUI to see what you marked you just need to do the following at the command line to access your clean array. (Numbers are random things I marked as not clean.

I have to leave right now so I can't address the second bullet about changing channels and skipping the ~clean elementr ... but it shouldn't be very hard. I will get back here in a couple of hours.

>> global clean
>> find(~clean)
ans =
  3  4  11 19

MODIFIED CODE: EDIT: Added code protection at the edges for skipping channels.

function cleanData(data)
% data = rand(19,1000,134);
global clean
clean = ones(1,size(data,3));
f = figure('Units','Normalized','Position',[0.25 0.25 0.5 0.5]);
a =   axes('Units','Normalized','Position',[0.05 0.15, 0.75 0.75]);
s =   uicontrol(f, 'Style','Slider', 'Units','Normalized','Position',[0.05 0.025, 0.75 0.05],...
                   'Min',1,'Max',size(data,3),'Value',1, 'Callback',{@sliderChange,a});
l =   uicontrol(f, 'Style','listbox','Units','Normalized','Position',[0.85 0.15, 0.1, 0.75],...
                   'String',cellstr(num2str([1:size(data,1)]')),'Callback',{@changeChannel,a,s,data});
c = uicontrol(f, 'Style','pushbutton','Units','Normalized','String','Not clean',...
                   'Position',[0.85 0.025 0.1 0.05],'Callback',{@notClean,s,a});

stepSize = 1/(s.Max - s.Min);
s.SliderStep = [stepSize 2*stepSize];               
changeChannel(l,[],a,s,data)

function changeChannel(l,evtData,a,s,data)
cla(a);
chanNum = str2double(l.String{l.Value});
sR = 500;  %500Hz
tempData = reshape(data(chanNum,:,:),[],size(data,3)); %Reshape each epoch into a column
tempTime = [0:1/sR:(size(data,2)-1)/sR]' + (0:1:size(data,3)-1)*2; %Build time array
plot(a,tempTime,tempData) %plot all the lines
s.Value = 1; %Rest Slider Position

function sliderChange(s,evtData,a)
global clean
persistent prevI

if isempty(prevI)
    prevI = 1;
end

viewI = round(s.Value);
sDir = sign(viewI - prevI);  %-1 if going backwards +1 if going forward
prevI = viewI;

if clean(viewI) == 0
    newPos = viewI + sDir;
    if newPos < 1 || newPos > s.Max
        return
    end
    s.Value = newPos; 
    sliderChange(s,[],a)
else
    disp(['Current Epoch: ' num2str(viewI)]) %console print
    xlim(a,[(viewI-1)*2 viewI*2] + [-.1 .1])  
end


function notClean(c,evtData,s,a)
global clean %Call the global
num = round(s.Value);
clean(num) = 0;
disp(['Epoch ' num2str(num) ' not clean']) %console print
%Advance to the next slider position.
if num+1 < s.Max
    s.Value = num+1;
    sliderChange(s,[],a)
end

Upvotes: 1

Mathieu
Mathieu

Reputation: 5746

Modified code working with second part too:

function cleanData(data);
% data = rand(19,1000,134);
f = figure('Units','Normalized','Position',[0.25 0.25 0.5 0.5]);
a =   axes('Units','Normalized','Position',[0.05 0.15, 0.75 0.75]);
s =   uicontrol(f, 'Style','Slider', 'Units','Normalized','Position',[0.05 0.025, 0.75 0.05],...
                   'Min',1,'Max',size(data,3),'Value',1, 'Callback',{@sliderChange,a});
l =   uicontrol(f, 'Style','listbox','Units','Normalized','Position',[0.85 0.15, 0.1, 0.75],...
                   'String',cellstr(num2str([1:size(data,1)]')),'Callback',{@changeChannel,a,s,data});
c = uicontrol(f, 'Style','pushbutton','Units','Normalized','String','Not clean',...
                   'Position',[0.85 0.025 0.1 0.05],'Callback',{@notClean,s,a});

stepSize = 1/(s.Max - s.Min);
s.SliderStep = [stepSize 2*stepSize];               
changeChannel(l,[],a,s,data)

function changeChannel(l,evtData,a,s,data)
cla(a);
chanNum = str2double(l.String{l.Value});
sR = 500;  %500Hz
tempData = reshape(data(chanNum,:,:),[],size(data,3)); %Reshape each epoch into a column
tempTime = [0:1/sR:(size(data,2)-1)/sR]' + (0:1:size(data,3)-1)*2; %Build time array
plot(a,tempTime,tempData) %plot all the lines
s.Value = 1; %Rest Slider Position

function sliderChange(s,evtData,a)
global clean
viewI = round(s.Value);
if clean(viewI) == 0
    s.Value = s.Value+1;
    sliderChange(s,[],a)
else
    disp(['Current Epoch: ' num2str(viewI)]) %console print
    xlim(a,[(viewI-1)*2 viewI*2] + [-.1 .1])  
end


function notClean(c,evtData,s,a)
global clean %Call the global
num = round(s.Value);
clean(num) = 0;
disp(['Epoch ' num2str(num) ' not clean']) %console print
%Advance to the next slider position.
s.Value = num+1;
sliderChange(s,[],a)

Upvotes: 1

Related Questions