Break / Stop while loop from user input at the Matlab command line - matlab

I am attempting to create a while loop that will loop continuously until input from the user at the command line.
I have tried two implementations of this the first, the first derived from this bit of python. The problem being that you must enter something other than exit every time you want to iterate through loop.
global active
active = true;
while active == true
userInput = input('enter: ','s');
inputHandler(userInput)
disp(rand)
pause(1);
end
function inputHandler(value)
global active
if value == 'exit'
active = false;
end
end
The second was
global loopFlag
loopFlag = true
while loopFlag == true
%some awesome code happens here
end
with the idea being that you could enter at the command line loopFlag = false while the code was executing and it would stop.
I know this can be done through the use of a toggle button but I would prefer not to have to go that route unless absolutely necessary.

active = true;
while active == true
active = input('Enter true or false ' );
disp(rand)
pause(1)
end

Related

Stop fminsearch when objective function reach certain value

How to stop fminsearch when objective function exceeded certain value (minima or maxima)
options = optimset('MaxFunEvals',9999);
[x,fval,exitflag,output] = fminsearch(#(var)objectiveFunction(variables), changingParameters,options);
How to stop the function if I reach certain objective function value (for example 1000) [within the 9999 iterations]
I've tried 'TolFun' , I am not sure if this is correct
options = optimset('MaxFunEvals',999,'TolFun',1000);
[x,fval,exitflag,output] = fminsearch(#(var)objectiveFunction(variables), changingParameters,options);
You can manually stop the search procedure by placing an appropriate function in the options.OutputFcn input struct. This function is called in every iteration of the search, and permits to signal back that the search is to be terminated. For example, you could define
function stop = custom_stop_fun(~, optimValues, ~)
if optimValues.fval >= 1000
stop = true;
else
stop = false;
end
end
and then set it via
options.OutputFcn = #custom_stop_fun;
Check out the full OutputFcn documentation

Matlab - Is there a way to capture messages sent to the workspace?

I'm working on a GUI (without GUIDE) in Matlab. The GUI will ultimately be compiled to an application and released to my coworkers.
My GUI calls some custom functions I wrote ages ago. These custom functions display status/progress messages to the workspace window.
As I understand it, I could have my executable write those messages to a log file, but then that leaves the user without any status updates on the GUI while the program is running.
I'm working on some pretty intensive 3D data manipulation, which has the potential to run for 5-10 minutes between function calls, so while I could provide status updates between function calls, it still leaves the end user with no idea what's going on and/or the appearance that the program locked up.
What I would like to do is to have something that works akin to the 'try-catch' method, where there's some way I can execute a function and capture messages intended for the workspace and redirect them to a uicontrol text box.
:EDIT:
I'm adding this for posterity, in the event anyone wants to use it. This is a functional demo that shows how to implement Peter's answer below.
First, create and save a function called "EndlessLoop":
function EndlessLoop(handles,loopCallback)
if nargin<1
handles = [];
loopCallback = #loop_Callback;
else
disp('Callback already set!');
end
tic;
abort = false;
while true
statusText = sprintf('Current Elapsed Time:\n%.2f',toc);
abort = loopCallback(handles,statusText);
if abort
statusText = sprintf('Abort request processed.\nEnding now.');
[~] = loopCallback(handles,statusText);
break;
end
pause(0.1);
end
return;
function abort = loop_Callback(~,myText)
clc;
abort = false;
disp(myText)
return;
Then, create a GUI that calls on EndlessLoop:
function TestGUI
close all;
myTest = figure('Visible','on','Units','normalized','Position',[0.1 0.1 0.8 0.8],'Name','Test GUI','NumberTitle','off');
set(myTest,'menubar','none');
handles = guihandles(myTest);
handles.goButton = uicontrol('Style','pushbutton','Units','normalized','Position',[0 0.5 0.5 0.5],'String','Go');
handles.abortButton = uicontrol('Style','pushbutton','Units','normalized','Position',[0 0 0.5 0.5],'String','Abort','Enable','off');
handles.statusText = uicontrol('Style','text','Units','normalized','Position',[0.5 0 0.5 1],'String','Press Go when ready.');
set(handles.goButton,'Callback',#goButton_Callback,'interruptible','on');
set(handles.abortButton,'Callback',#abortButton_Callback,'interruptible','on');
handles.abortButton.UserData = false;
guidata(myTest,handles);
return;
function goButton_Callback(hObject,~)
handles = guidata(gcbo);
hObject.Enable = 'off';
handles.abortButton.Enable = 'on';
EndlessLoop(handles,#StatusUpdate)
handles.abortButton.String = 'Abort';
handles.abortButton.Enable = 'off';
hObject.Enable = 'on';
pause(0.5);
handles.statusText.String = 'Press Go to start again.';
handles.abortButton.UserData = false;
guidata(gcbo,handles);
return;
function abortButton_Callback(hObject,~)
handles = guidata(gcbo);
if handles.abortButton.UserData
handles.abortButton.UserData = false;
hObject.String = 'Abort';
else
handles.abortButton.UserData = true;
hObject.String = sprintf('Abort pending...');
end
guidata(gcbo,handles);
return;
function abort = StatusUpdate(handles,statusText)
clc;
abort = handles.abortButton.UserData;
disp(handles.abortButton.UserData)
handles.statusText.String = statusText;
return;
A couple things I found when playing with this trying to get it to work:
I have been just adding variables to the handles structure for whatever I needed. In this case it would have been handles.abortRequest = false;. However, it appears that when I pass handles to the EndlessLoop function it becomes stale - handles never updates again. To get around this, I had to store what I wanted in the UserData section of the abortButton. I think this is because the handle to abortButton is still valid, because it hasn't changed, and I get fresh UserData because I'm able to poll with the valid handle. I can't access handles.abortRequest because it's not an object - I can't poll it; it simply exists, and it exists in the "snapshot" that was when I sent handles to EndlessLoop. At least, this is my understanding.
I needed to set the 'Interruptible' property of the goButton callback to 'on' in order for the abortButton to function while the process "hung" on EndlessLoop. With Interruptible set to off no other callbacks may be processed until that particular callback completes, which will never happen with endless loop.
So, in conclusion, this is a complete functional example that answers my question. Thanks to Peter for the answer - this also includes his ProTip of being able to pass an abort option back to the process that's taking a long time to complete. I've never used callbacks like this before so hopefully others will find this useful in the future.
This answer elaborates on my comment to the question.
Assume you have function that outputs stuff to the command window:
function out = longcomputation(param1, param2)
%
while(for_a_long_time)
process_one_step();
percent_complete = something;
fprintf('Step result: %f Complete: %f', stuff, percent_complete);
end
You can make the output function configurable by passing a function handle. Here I'm making it optional by testing nargin:
function out = longcomputation(param1, param2, outputfcn)
function display_progress_to_console(msg, percentage)
sprintf('%s, Complete %f', msg, percentage);
end
if(nargin < 3) % Supply a default output function if none passed in
outputfcn = #display_progress_to_console;
end
while(for_a_long_time)
process_one_step();
percent_complete = something;
msg = sprintf('Step result: %f', stuff);
outputfcn(msg, percent_complete);
end
Now, in your GUI, you can define and pass in a different output callback. This can live right in your GUI code so that the function has access to the GUI objects you need.
ProTip: In addition, have this callback function return true or false to signal the user's desire to abort. The GUI can then present a cancel button to drive that return value, and the long-running code can periodically send the status message AND check if abort has been requested.
You could potentially use the built-in diary functionality to accomplish something similar to what you're trying to do.
diary on % Uses "diary" for filename
diary('logfile.log') % Custom filename
This will write all command line output to the specified file. Then you can periodically poll this file and update your uicontrol with the contents (or last few lines if you want).
logfile = 'logfile.log';
diary(logfile);
u = uicontrol('style', 'text');
% Check every 5 seconds
t = timer('Period', 5, ...
'ExecutionMode', 'FixedRate', ...
'TimerFcn', #(s,e)populate(s));
start(t);
function populate(src)
fid = fopen(logfile, 'rb');
contents = fread(fid, '*char').';
set(src, 'String', contents);
fclose(fid);
end

While debugging with an input from the keyboard, I want to able to skip the execution of a few lines of code in MATLAB

Currently I have this excerpt of code I am trying to debug:
if (white_flag == 1)
keyboard;
imshow(rl_img);
N = N+1;
times(times_index,1) = index;
while(white_flag == 1)
imshow(rl_img);
index = index+1;
%%% If statement for when the loop has run out
if (index >= frames)
break
end
%%% Initial Image Pre-Processing
rl_img = ones(mod_height,width);
pre_rl_img = medfilt2(vreader.read(index));
for i = 1:mod_height
for j = 1:width
rl_img(i,j) = pre_rl_img(i,j);
end
end
white_flag = detect_white( rl_img, white_flag );
end
times(times_index,2) = index;
times_index = times_index+1;
else
index = index+ 1;
end
Now, as you can see, the debug keyboard input call keybaord is on the second line. While this allows me to efficiently see each step of the execution of my program, I do not understand how to skip over the part below:
for i = 1:mod_height
for j = 1:width
rl_img(i,j) = pre_rl_img(i,j);
end
end
This is a rather sizable picture(rl_img), so waiting for keyboard input while I scrawl through the code manually wastes a lot of time. Can someone please tell me how to skip the user input execution of these lines of code while I debug the program?
Please do not hesitate to ask me any questions that can clarify this problem. Thank you for all your answers!
The answer is quite straightforward:
you set a breakpoint after the lengthy loop,
when you decide to run automatically all the rest of the loop up to the breakpoint you just set, press [F5] (Continue).
This assumes that you debug your code in the normal MATLAB IDE.
If I understand your problem correctly, you don't want to step through each loop iteration.
You can either follow CST-Link's advice or you can avoid creating additional breakpoints by placing your cursor somewhere after the loop
and clicking
on the editor's debug panel.

Closing MATLAB GUI application programmatically without using error()

I am trying to make it so the application/gui closes completely if the user clicks cancel or exit of an input dialog. The tag of my gui is called window however using close(handles.window); leads to the program looping through once and then (after the user clicks cancel or exit again) reaching the close(handles.window); line which, of course, leads to an Invalid figure handle error.
Is there any method to close the application without the need for producing an error and not closing the entire MATLAB environment (like quit and exit). The error() is my temporary fix which works but I don't want the application to seem like it has crashed.
I have tried close all but that has no effect. It's worth noting that the application does reach inside the if statement if the user clicks cancel or exit.
I have also tried setting a variable and having the close commands outside the while loop.
apa = getAvailableComPort();
apList = '';
i = 0;
for idx = 1:numel(apa)
if i == 0
apList = apa(idx);
else
apList = strcat(apList, ', ', apa(idx));
end
i = i + 1;
end
prompt = {'Enter COM PORT:'};
title = 'COM PORT';
num_lines = 1;
def = apList;
COM_PORT = inputdlg(prompt,title,num_lines,def);
% Keep asking for a COM PORT number until user gives a valid one
while sum(ismember(apa, COM_PORT)) == 0 % If the COM port comes up in the available COM ports at least once
% If user clicks cancel, close the guide
if isempty(COM_PORT) == 1
error('Closing...'); % HERE IS THE PROBLEM
end
prompt = {'Invalid COM PORT'};
title = 'Invalid COM PORT';
COM_PORT = inputdlg(prompt,title,num_lines,def);
end
The function getAvailableComPort is found at http://www.mathworks.com/matlabcentral/fileexchange/9251-get-available-com-port
This entire piece of code is at the top of the gui_OpeningFcn() function.
Have you tried putting a break after the close(handles.window). The break will exit the while loop so it won't hit that line again.
if isempty(COM_PORT) == 1
close(handles.window)
break
end
This way the while loop stops after closing the window. IF you need to do more cleanup besides just closing the window then set an error flag .
%Above while loop
errorFlag = False;
if isempty(COM_PORT) == 1
close(handles.window)
errorFlag = True;
break
end
%OutSide of While loop
if errorFlag
%Do some more clean-up / return / display an error or warning
end
Also FYI, you don't need to do isempty(COM_PORT) == 1 ... isempty(COM_PORT) will return true/false without the == 1
Your requirements aren't really clear, but can't you just protect the close operation by doing
if ishandle(handle.window)
close(handle.window)
end
This will prevent the close from being attempted if the window has already been destroyed.
Why don't you use a simple return and a msgbox to inform that user has clicked on Cancel?
if isempty(COM_PORT)
uiwait(msgbox('Process has been canceled by user.', 'Closing...', 'modal'));
delete(your_figure_handle_here);
return;
end
I tried using the return statement in conjunction with close(handles.window) but received the error:
Attempt to reference field of non-structure array.
Error in ==> gui>gui_OutputFcn at 292 varargout{1} = handles.output;
So it seems just removing that line on 292 solved the issue.

Is there an quivalent to 'jump' or 'go to' in Matlab?

I have this code:
values_nodelay = no_of_values(2:2:end)
no_of_values_x1 = (find(u~=[u(2:end), u(end)+1]));
no_of_values_x1 = no_of_values_x1(2:2:end)
l = 1;
delay = 2;
values_delay = [];
while l<=length(values_nodelay)
values_delay_temp = values_nodelay(l)-delay;
if delay>values_delay_temp
end
values_delay = [values_delay, values_delay_temp];
l = l+1;
end
values_delay
I need a goto or jump function to the beginning of while, or an equivalent if anyone
knows an easier way, that if delay > values_delay_temp, it won't become part of the final vector values_delay. Instead, I want to skip it and continue again with the while loop.
Rather than using jumps like continue or break, you could just do this:
if delay<=values_delay_temp
values_delay=[values_delay, values_delay_temp];
end
In other words make the "default" behavior of the loop to do nothing, and then only increment your vector when you hit the right condition. It's much clearer and easier to debug.
Also instead of using vector concatenation like you have, I've found it's more efficient to do values_delay(end+1) = values_delay_temp; if you have to grow a vector in a loop.
The continue statement will stop the execution of a loop for the current iteration and continue with the next iteration, e.g.
while foo
# stuff that will execute for all iterations
if bar
continue
end
# stuff that won't execute if bar is false
end
Although, in your specific case, why don't you just issue
values_delay=[values_delay, values_delay_temp];
and increase the loop counter when
delay <= values_delay_temp
is true?