Debugging a sequence of anonymous functions

Suppose you were given this code that loads a sequence of images stored in mat files but the code doesn't run out of the box.
clear data;
data.vis.path = '/data/images_vis_v2/';
data.vis.meta = load(fullfile(data.vis.path,'meta_data.mat'));
data.vis.files = dir(fullfile(data.vis.path,'*_frame.mat'));
data.lwir.path = '/data/images_lwir_v2/';
data.lwir.meta = load(fullfile(data.lwir.path,'meta_data.mat'));
data.lwir.files = dir(fullfile(data.lwir.path,'*_frame.mat'));
for sensor = {'vis','lwir'}
data.(sensor{1}).times = [];
for k=1:numel(data.(sensor{1}).files)
tok = regexp(data.(sensor{1}).files(k).name,'(\d{7})_frame.mat','tokens');
if ~isempty(tok)
data.(sensor{1}).times = [data.(sensor{1}).times,str2double(tok{1}{1})];
end
end
data.(sensor{1}).times = sort(unique(data.(sensor{1}).times));
end
data.times = sort(unique([data.vis.times,data.lwir.times]));
data.filename = @(sensor,index) fullfile(data.(sensor).path,sprintf('%07d_frame.mat',data.times(index)));
data.loadvar = @(sensor,field,index) getfield(nthout(1, @() load(data.filename(sensor,index),field)),field);
data.image = @(sensor,index) cellout(data.loadvar(sensor,'O_ref',index));
data.vis.camera = data.vis.meta.cams_used{1};
data.lwir.camera = data.lwir.meta.cams_used{1};
nrml = @(x) single(x)/max(single(x(:)));
get_image = @(n) nrml(data.image('vis',n+1));
fig = figure(1); clf; colormap(fig,'gray');
frame_numbers = [0:10:50];
images = arrayfun(@(n) get_image(n), frame_numbers, 'UniformOutput', false);
poses = arrayfun(@(n) eye(4), frame_numbers(2:end)-1, 'UniformOutput', false);
Instead you get the following stack trace:
Error using load
Unable to read file '/data/images_lwir_v2/0170218_frame.mat'. No such file or directory.
Error in stub (line 23)
data.loadvar = @(sensor,field,index) getfield(nthout(1, @() load(data.filename(sensor,index),field)),field);
Error in nthout (line 7)
case 1, [value] = feval(fcn, varargin{:});
Error in stub (line 23)
data.loadvar = @(sensor,field,index) getfield(nthout(1, @() load(data.filename(sensor,index),field)),field);
Error in stub (line 24)
data.image = @(sensor,index) cellout(data.loadvar(sensor,'O_ref',index));
Error in stub (line 28)
get_image = @(n) nrml(data.image('lwir',n+1));
Error in stub (line 32)
images = arrayfun(@(n) get_image(n), frame_numbers, 'UniformOutput', false);
Error in stub (line 32)
images = arrayfun(@(n) get_image(n), frame_numbers, 'UniformOutput', false);
How do you debug anonymous functions? Is there a way to put break points or step in? What about a pipeline of anonymous functions?

9 comentarios

Stephen23
Stephen23 el 25 de Nov. de 2022
Editada: Stephen23 el 25 de Nov. de 2022
What is there to debug? The error is quite clear: your code is trying to LOAD a file that does not exist: "Unable to read file '/data/images_lwir_v2/0170218_frame.mat'. No such file or directory." The code looks like it is working exactly as intended. But its design does not take into account whether particular files exist (or not) before it tries to LOAD them... thus the error. From a quick look a the code, combinng the times data is a possible cause of that.
The code would probably be much clearer and easier to work with using normal functions and loops. Then you could easily add functionality to handle missing files.
seth patterson
seth patterson el 25 de Nov. de 2022
Editada: seth patterson el 25 de Nov. de 2022
My question was more conceptual than specifically debugging this example code. I have to use the anonymous functions as is. I was just wondering if there's a easy way to debug them. While it's clear in this specific example that the error is a missing file, what's not clear to me is how you debug a pipeline of anonymous functions. Since it's a pipeline of anonymous functions, each function executed on its own does not have an error.
Torsten
Torsten el 25 de Nov. de 2022
I was just wondering if there's a easy way to debug them.
No. That's why I usually avoid function handles and use functions instead. Therein, you have all possible options for debugging.
Stephen23
Stephen23 el 25 de Nov. de 2022
Editada: Stephen23 el 25 de Nov. de 2022
"I was just wondering if there's a easy way to debug them"
It depends on what you mean by "easy". If you are used to working with debugging tools, then it is quite easy: you can set breakpoints within anonymous functions or stop on errors/warnings, then once stopped you can move up and down the stack, run code, modify or display variables, etc., exactly like when you debug normal functions.
However if the term "debugging tools" means nothing to you, then there is a steep learning curve ahead:
seth patterson
seth patterson el 26 de Nov. de 2022
I'm familiar with debugging in Matlab (breakpoints and stepping in or over) but I was wondering specifically how to set breakpoints inside anonymous functions. I was hoping to inspect input arguments and return values.
Stephen23
Stephen23 el 26 de Nov. de 2022
Editada: Stephen23 el 26 de Nov. de 2022
"I was wondering specifically how to set breakpoints inside anonymous functions."
As Walter Roberson wrote eight hours ago, you just need to click (either right click or left click will work) in the LHS margin of the MATLAB editor:
And the editor will ask if you want to either set the breakpoint on the that line or inside the function:
This is exactly the same way that you would interactively set breakpoints using the editor anyway, and is explained in the MATLAB documentation under the title "Breakpoints in Anonymous Functions":
In my experience this is more convenient to use than DBSTOP command, if that is what you normally use.
seth patterson
seth patterson el 28 de Nov. de 2022
I'm not seeing this same dialog box in 2020b when I right click on the line where the anonymous function is defined
Stephen23
Stephen23 el 28 de Nov. de 2022
@seth patterson: are you trying it on the code shown in your question? It worked for me on the lines I tried. If you are attempting some other code, please upload it.
Where exactly are you clicking? In the margin?
seth patterson
seth patterson el 28 de Nov. de 2022
I was right clicking on the numbers. I just tried left clicking and it works. Thanks.

Iniciar sesión para comentar.

 Respuesta aceptada

Walter Roberson
Walter Roberson el 25 de Nov. de 2022
Editada: Walter Roberson el 25 de Nov. de 2022
"I have to use the anonymous functions as is. I was just wondering if there's a easy way to debug them"
No, there is not. You can right-click on the line number where you assign an anonymous function to a variable, and it might give you the option to put a breakpoint inside the function so defined, but it does not always give that option. In that case you have to track down the place where the function is invoked and put a breakpoint at the invocation, and then when the breakpoint is hit, you have to use the tools to step IN to the call.
When you are stopped at a breakpoint inside an anonymous function, you can use the usual tools to examine the workspace, but that workspace is often not going to be all that informative, possibly only showing you the named parameters. If you have configured for datatips in the editor, then you might be able to point to captured variables to examine them; otherwise you need to dbup until you get to a location that contains a handle to the anonymous function, and then you have to use functions to examine the Workspace of the anonymous function. Because functions returns a structure, you could try
functions(HANDLE).Workspace{1}
but chances are that you are going to want to assign the results into a variable in order to be able to examine the individual variables. Assigning the output of a function to a variable is fine in traditional MATLAB, but if you happen to be inside a function that was defined such that there is an end statement matching the function statement then the workspace is static and you cannot create new variables. In such a case you will need to use global to create a new variable to assign the results of the function call to, in order to be able to examine the captured variables.
If an anonymous function has captured variables, then there is no way provided by Mathworks to view the source for the anonymous function with the values of the captured variables substituted in for the names of the captured variables. For example,
w = rand();
F = @(t) sin(2*pi*w*t)
then there is no way to ask MATLAB to display sin(2*pi*0.3479351*t) [or as appropriate].

1 comentario

seth patterson
seth patterson el 26 de Nov. de 2022
Bummer, maybe math works could make some improvements in the future.

Iniciar sesión para comentar.

Más respuestas (0)

Categorías

Más información sobre Programming en Centro de ayuda y File Exchange.

Productos

Versión

R2022b

Etiquetas

Preguntada:

el 25 de Nov. de 2022

Comentada:

el 28 de Nov. de 2022

Community Treasure Hunt

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

Start Hunting!

Translated by