While debugging with an input from the keyboard, I want to able to skip the execution of a few lines of code in MATLAB - 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.

Related

Why is KbCheck in Psychtoolbox not registering keyboard input?

I'm trying to run a programme coded in Psychtoolbox-3 that should register a keypress. But when I run it, even just this section from the command window, it doesn't respond to the E, P keys (or any) and I have to stop the operation using Ctrl-C. I have tried changing it to {e, p} (which are the names I found using KbName('KeyNames')), but it doesn't work.
The same code works on my supervisor's computer - I am using a Mac with OS 11.1.
KbName('UnifyKeyNames');
keyresp = KbName({'E','P'});
key = 0;
while ~key
[key,tkey] = CheckKeyPress(keyresp);
end
The CheckKeyPress is this function (and it works - gives output 0):
function [key,tkey] = CheckKeyPress(whichkeys)
if nargin < 1 || isempty(whichkeys)
whichkeys = 1:256;
end
key = 0;
[iskeydown,tkey,keys] = KbCheck(-1);
if any(keys(whichkeys))
key = find(keys(whichkeys),1);
end
end
I have also tried looking at PsychHID('Devices') and my keyboard is there (and no other keyboards).
Thanks for any help!
Solved! It was a simple mac problem :)
After I tried KbQueueCreate and got an error message I found the same one on another thread - the only problem is I had to allow Matlab to access keyboard input on my laptop.
Settings - Security and Privacy - Input Monitoring
It is always a big pain in MacOs. I use this code:
close all
clear all
clc
ListenChar(0);
Devices=PsychHID('Devices');
keyboardsIDs = [];
for iiD = 1:numel(Devices)
try
KbQueueCreate(Devices(iiD).index);
KbQueueStart(Devices(iiD).index);
keyboardsIDs(end+1,1) = Devices(iiD).index;
end
end
stopScript = 0;
while ~stopScript
for iiD = 1:numel(keyboardsIDs)
[keyIsDown, firstPress]=KbQueueCheck(keyboardsIDs(iiD));
if keyIsDown
keyID = find(firstPress)
disp(keyID)
if any(keyID ==20), stopScript =1; end
end
end
end
for iiD = 1:numel(keyboardsIDs)
KbQueueStop(keyboardsIDs(iiD));
end
ListenChar();
UPDATE
This is a bit dirty workaround, but it will works in any situation.
Press 'q' to exit the loop

Insert a number before a given number in a linked list

I'm doing an introduction course in programing in matlab and python and I have only been coding for a short time, so I'm still on the basics.
In the problem that I'm trying to solve, we have been given a code that creates a linked list by the teacher.
classdef Elem < handle
%Elem A class realising a linked list.
properties
data
next = Elem.empty
end
methods
function node = Elem(value)
if (nargin > 0)
node.data = value;
end
end
function obj = insert(obj, value)
if(isempty(obj.next))
obj.next = Elem(value);
else
obj.next.insert(value);
end
end
% More methods go here
end
end
One of the questions is then to make a code that can insert a number before a number in the linked list.
To do this I have made this code.
function newlist=InsertBefore(list,newdata,dataBefore)
if ~isempty(list)
if list.data==dataBefore
newlist = Elem(newdata);
newlist.next = list;
elseif list.next.data==dataBefore
newlist=list;
newelem = Elem(newdata);
newelem.next = list.next;
newlist.next = newelem;
else
InsertBefore(list.next,newdata,dataBefore)
end
end
end
If I then write
linkedlist2=InsertBefore(LinkedList,4,12)
the function makes a new list with 4 in front of the 12 which is the first number in the list. so the "If" part of the code works fine. if I try doing the same thing with a number in the middle of the list it says.
Output argument "newlist" (and maybe others) not assigned during call to "InsertBefore".
I have tried many things but nothing has really worked perfect yet, so your help is much appreciated
Thanks
Lasse
SOLVED
Had to have
else
newlist = InsertBefore(list.next,newdata,dataBefore)

Receive Mail if matlab is in debugging mode

I'd like to receive an email when Matlab is in debugging mode, so I tried the following:
timerTic=4; % how often the timer checks
timerHandle = timer();
timerHandle.startDelay = timerTic;
timerHandle.Period = timerTic;
timerHandle.ExecutionMode = 'fixedRate';
timerHandle.TasksToExecute = inf;
timerHandle.TimerFcn = #CheckDebugMode;
j=0;
while t==0
j=j+1;
end
where the funcion is:
function CheckDebugMode( ~ )
% Check if Matlab is in Debug mode
if feature('IsDebugMode')
sendSSLmail('mymail#mycountry','Matlab is in debug mode','Matlab is in debug mode')
end
t doesn't exist so that an error occurs and Matlab enters in debug mode (dbstop if error is active).
feature('IsDebugMode') is equal to 1, but I receive no mail.
It's the first time I work with objects in Matlab, so I'm pretty sure the code is in someway wrong.
Maybe someone can help me?
Thanks in advance
Do you start your timer?
start(timerHandle)
edit I haven't tested this but I suspect you have problems with your function handle and the function itself. The timer passes arguments to your function, so you need to accept then in your code:
function CheckDebugMode( varargin )
or stop then from being passed:
timerHandle.TimerFcn = #(~,~)CheckDebugMode

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?