Matlab stop function's execution - matlab

I have an array. I am processing elements of this array in a for loop inside a function.
function results = processArray(array)
for ii = 1:length(array)
%some stuff here
results(ii) = %getting the results for this particular element
end
end
There might be a lot of elements and computations might take a lot of time. I want to be able to finish execution of the for loop at any arbitrary time when a user wants to do that so that the results for already processed elements would be available.
I was trying to make a figure with a button which would change a boolean flag. Inside the for loop I was checking the value of that boolean. If the boolean changed then the for loop should break.
function results = processArray(array)
fig = figure;
fig.UserData.continue = 1;
uicontrol('Parent', fig', 'Style', 'pushbutton', 'String', 'stop', 'callback', #interrupt)
for ii = 1:length(array)
if(fig.UserData.continue == 0)
break;
end
%some stuff here
results(ii) = %getting the results for this particular element
end
end
function interrupt(obj, ~)
fig = obj.Parent;
fig.UserData.continue = 0;
end
well, that does not work. The figure shows up only after all the computations are done already. If I draw the figure first using something like waitforbuttonpress and proceed to the for loop pressing the button does not stop the execution. I think the callback function is being executed only after the for loop is finished. Is there any way to solve this?

You will need to drawnow after you create the button, so it will show up. You also need to drawnow within the loop to update the button state. Then you should achieve what you want.
drawnow force figure update, so it will slow down your computation a little.

Related

Matlab imrect in infinite loop

I have a Matlab UI where I want the user to input several areas using imrect as soon as a radiobutton is selected.
It is unknown how many areas will be selected so the selection needs to be in an infinite loop.
As soon as another radiobutton is selected, the imrect input should stop, which I cannot get to work.
Here is a minimal working example:
function mwe
ax = axes('Position', [0 0 1 1]);
bg = uibuttongroup('Position',[0 0 .15 1], 'SelectionChangedFcn',{#bselection, ax});
r1 = uicontrol(bg, 'Style','radiobutton', 'String','Option 1', 'Position',[10 250 100 30]);
r2 = uicontrol(bg, 'Style','radiobutton', 'String','Option 2', 'Position',[10 225 100 30], 'Value',1);
function bselection(source, event, ax)
switch event.NewValue.String
case 'Option 1'
while true
h = imrect(ax);
% do stuff
delete(h);
end
case 'Option 2'
% do not show imrect and do other stuff
end
I appreciate any help.
You can set the Interruptible property on the button. You can also set BusyAction to cancel. The help says:
The interruption occurs at the next point where MATLAB processes the
queue, such as when there is a drawnow, uifigure, getframe, waitfor,
or pause command.
So if you include a 'pause', it may not stop until the next rectangle has been selected. This is because once you've called imrect, it may not know that it has to stop.
However this method may not work if imrect blocks the matlab UI from triggering a callback.
An altogether better way is not to use an endless loop. You need to tell it when to end by checking --
running = true;
while running
h=imrect(ax)
% do stuff
delete(h)
if (SOMETHING)
running = false
end
end
What is SOMETHING? We need to check if the button has been deselected.
You could use
if r1.Value!=1
running = false
end
Which would check if r1 is not selected, and if so, running becomes false, and the loop stops cycling round.

How to update date and time in matlab gui

function demo1()
H.f = figure('Name','DEMO1');
set(H.f,'Units','Pixels','Position',get(0,'ScreenSize'));% adjust figure size as per the screen size
H.pb1 = uicontrol('style','push',...
'units','pixels',...
'position',[400 800 280 30],...
'fontsize',14,...
'string', datestr(now)); % datestr(now) is used to get current date and time
end
how i can get the real time clock in gui
This is not really an easy task to perform and you may want to think about your design. This could be wrapped in a class, but not necessarily. In case you do not want to do this you may be able to modify the underlying Java objects, but that seems to be overworking this. I have instead structured this in a more C-style manner with placing all data in a struct and writing functions taking the struct as an argument. However, since matlab does not support passing memory locations you need to return the struct after modifying it.
I have chosen to use a timer object for this. You need to store the timer object somewhere since it needs to be deleted when you are not using it anymore. Further, I have added some code for using a start function and stop function as well. For the timer object. This for seeing that the object actually gets finished during development phase. This is not needed for the final project. Further, you may want to handle the case where the window is closed. This will cause the current implementation to crash since the timer is independent of the figure and does not stop when the figure is closed. You probably want to call stop_timer on closing the figure. Anyway here is the code:
function test()
h.f = figure('Name','DEMO1');
set(h.f,'Units','Pixels','Position',get(0,'ScreenSize'));% adjust figure size as per the screen size
h.pb1 = uicontrol('style','push',...
'units','pixels',...
'position',[400 800 280 30],...
'fontsize',14,...
'string', datestr(now)); % datestr(now) is used to get current date and time
h = start_clock(h);
pause on;
pause(15);
pause off;
h = stop_clock(h);
end
function obj = start_clock(obj)
%TasksToExecute calls the timer object N times
t = timer('StartDelay', 0, 'Period', 1,... % 'TasksToExecute', inf, ...
'ExecutionMode', 'fixedRate');
t.StartFcn = {#my_callback_fcn, 'My start message'};
t.StopFcn = { #my_callback_fcn, 'My stop message'};
t.TimerFcn = {#set_time, obj};
obj.t = t;
start(obj.t);
end
function obj = stop_clock(obj)
stop(obj.t);
delete(obj.t);
end
function set_time(obj, event, arg)
arg.pb1.String = datestr(now);
end
function my_callback_fcn(obj, event, arg)
txt1 = ' event occurred at ';
txt2 = arg;
event_type = event.Type;
event_time = datestr(event.Data.time);
msg = [event_type txt1 event_time];
disp(msg)
disp(txt2)
end

Matlab gui with pause function

I am using the GUIDE for matlab gui.
The gui built in order to communicate with keithley current measurement device through GPIB.
When using a toggle button for Current measurement while loop, i am using a pause() function inside the while loop for each iteration and a ytranspose on the y array reading results.
function Measure_Callback(hObject, eventdata, handles)
global GPIB1
global filename
global timeStep
disp('Measurement in progress \n stopwatch starts!');
tic
x=0;
n=0;
while get(hObject,'Value')
fprintf(GPIB1, 'printnumber(smua.measure.i(smua.nvbuffer1))');
fprintf(GPIB1, 'printbuffer(1,1,nvbuffer1)');
A = fscanf(GPIB1);
if length(A)<20
x = x+1;
n = n+1;
t(n) = toc ;
y(x) = str2double(A);
plot(t,y,'-bo',...
'LineWidth',2,...
'MarkerEdgeColor','k',...
'MarkerFaceColor',[.49 1 .63],...
'MarkerSize',10);
grid on
hold on
end
title('Current vs Time','FontSize', 15)
xlabel('Time [s]','FontSize', 15)
ylabel('Current [A]','FontSize', 15)
a = timeStep;
pause(a)
end
disp('Measurement terminated');
disp('Elapsed time: ');
elapsedtime = toc;
elapsedtime_string = num2str(elapsedtime);
disp(elapsedtime_string);
ytrans = transpose(y);
csvwrite(filename,ytrans);
fprintf(GPIB1, 'smua.source.output = smua.OUTPUT_OFF');
For the pause function i'm geting error:
?? Error using ==> pause Error while evaluating uicontrol Callback
For the transpose(y) function i'm also getting a error:
its undefined y.
Cant understand why are those errors and could use some help.
Thank you!
First off, as people say, post the errors and the code. Do you know if length(A) is smaller than 20 in the first time you run the loop? Because if not, A is not defined and you can't transpose something that is not there. Initialize A before the loop to something and see if the error persists (or print out length(A) to make sure the loop gets entered the first run).
As for the pause error, make sure pause is an int or double, not a string. If you get your global timeStep from the GUI field, it is probably a string and you need to covert it to double first.

Is this a race condition in matlab?

The title says it all. I was wondering if the following code is prone to a race condition.
classdef Foo < handle
properties
value = true
end
methods
function toggle(o, ~, ~)
o.value = ~o.value;
end
end
end
function main
foo = Foo;
uicontrol('style', 'pushbutton', 'callback',#foo.toggle);
drawnow
%// Endless loop which gets broken up by a button press
while foo.value
pause(1)
end
%// What happens if I press the button twice, really fast? There
%// is no external function called between here and the previous
%// while loop.
if foo.value
error('Race')
else
fprintf('\nWe made it\n')
end
Am I save from the race condition since everything happens in the event dispatch thread? Is the same still true if I play with Interruptible and BusyAction property of the button? I found the matlab help quite confusing.
In case it matters I'm using R2012a.

How do I alter a variable with a uicontrol callback function?

The big picture goal is to successively plot an image sequence at some rate and pause the process when the pushbutton is pressed. Then resume the process upon hitting the space bar or pressing the pushbutton or whatever. Here is the code I have so far with a simple rand/pause(0.5) procedure for each iteration of the loop (instead of plotting my images).
My issue is this:
ButtonCallback seems to be invoked when the pushbutton is pressed, and DoPause is set to 1 in the callback function, BUT DoPause is not changed in the main function PauseButtonTest. How do I change this variable so the if statement in my while loop is executed.
Any help is appreciated. Thanks.
function PauseButtonTest
DoPause = 0;
hb = uicontrol('Style','Pushbutton','String','Pause','FontWeight','Bold', ...
'Callback',#ButtonCallback,'Unit','Normalized','Position',[0 0 1 1]);
while ishandle(hb)
if DoPause
disp('You pushed the button')
pause
DoPause = 0;
set(hb,'Enable','On')
drawnow
end
% Computations/Plot successive figures/etc.
rand
pause(0.5)
end
end
function ButtonCallback(hObj, event)
DoPause = 1;
disp('You are in ButtonCallback')
disp(['DoPause = ' num2str(DoPause)])
set(hObj,'Enable','off')
end
Nested functions.
Just move function ButtonCallback(hObj, event) ... inside PauseButtonTest so that it has access to its variables ("externally scoped" variables). Plop it down a couple of lines below the while loop and before the end that signals the end of PauseButtonTest.