How to use 'UniformOutput' and 'ErrorHandler' together in 'arrayfun' function?

I am using 'arrayfun' function to run a function of an array which gives output logical true/false or nan depending upon trajectory of animal. Here 0.5 is the length on the central zone in X and Y direction since it is a 2-dimensional zone.
[id, output] = arrayfun(@(id) passingCentralZoneRejectInitialPresence(id,0.5), ...
input_data.id(startRow:endRow),'UniformOutput', false, 'ErrorHandler',@(s,varargin) false());
I understand since my output could be logical or double I have to use 'UniformOutput', false. But I don't understand how to use error handler in this case. The one I am using here is an answer to my previous post. (Thanks for that) I wanted logical false as output for the trials with bad data.
Can anyone please check if my code is correct and explain what is 'ErrorHandler' doing in this case or direct me to a more elaborate documenation?

 Respuesta aceptada

Stephen23
Stephen23 el 13 de Dic. de 2022
Editada: Stephen23 el 13 de Dic. de 2022
"Can anyone please check if my code is correct..."
It is not: you have called ARRAYFUN() with two output arguments, therefore both the function applied to the array and the ErrorHandler will need to also return two output arguments. Your ErrorHandler function only returns one output argument.
"...and explain what is 'ErrorHandler' doing in this case or direct me to a more elaborate documenation?"
The ErrorHandler function is very simple: if the main function applied to the array throws an error for any specific input array elements (so does not provide any output values), then the ErrorHandler is called to provide those output elements. Clearly if you request two output arguments from ARRAYFUN(), then both functions must provide two output arguments.
You can see the example in the documentation also has two output arguments. It defines a function (in a file), not an anonymous function, but you can use DEAL() to return mutlple outputs from an anonymous function:
fnh = @(id) passingCentralZoneRejectInitialPresence(id,0.5);
erf = @(varargin) deal(false);
[id, output] = arrayfun(fnh, input_data.id(startRow:endRow), ...
'UniformOutput',false, 'ErrorHandler',erf);

4 comentarios

Thanks for your response. I looked at the shared links. It makes sense to me that I need 2 outputs in ErrorHandler function. I guess 1 of them were false in my script. But I could not figure out how to fix the issue. I want 'id' (datatype: double) to be one of the output, the error in the function passingCentralZoneRejectInitialPresence should not affect this output. I tried
[id, output] = arrayfun(@(id) passingCentralZoneRejectInitialPresence(id,0.5), ...
input_data.id(startRow:endRow),'UniformOutput', false, 'ErrorHandler', ...
@(s,varargin) [id, false()]);
But that did not work.
"But that did not work."
At least two bugs:
  1. You concatenated two things into one array and returned one array. One array is only one array, it is not two output arguments. I already explained and showed you in my answer how to return multiple outputs from an anonymous function: use DEAL(). That is also explained in the DEAL() documentation, which I linked to in my answer. It is unclear why you ignored that and invented something else.
  2. Your ErrorHandler anonymous function uses the variable id but does not define it anywhere. The ARRAYFUN() documentation already tells you that "The remaining input arguments to the error handler are the input arguments for the call to func that made func throw the error", so we can simply use those inputs to exactly get the value you want:
fnh = @(id) passingCentralZoneRejectInitialPresence(id,0.5);
erf = @(~,id,varargin) deal(id,false);
[id, output] = arrayfun(fnh, input_data.id(startRow:endRow), ...
'UniformOutput',false, 'ErrorHandler',erf);
PS: don't force everything into one line, just because you can. Add clarity and make your debugging easier by not squeezing everything together into a mad jumble of spaghetti. Making code easier to read aids your future self.
PPS: lets try that error handler and see if it works:
arr = {1,2,uint8(3),4}; % fake data: three doubles and one integer type.
fnh = @(id) deal(sqrt(id),true); % SQRT() fails on integer data types.
erf = @(~,id,varargin) deal(id,false);
[val,boo] = cellfun(fnh, arr, 'UniformOutput',false, 'ErrorHandler',erf)
val = 1×4 cell array
{[1]} {[1.4142]} {[3]} {[2]}
boo = 1×4 cell array
{[1]} {[1]} {[0]} {[1]}
val{:}
ans = 1
ans = 1.4142
ans = uint8 3
ans = 2
So far everything is working exactly as expected and documented.
I appreciate you taking your time and effort to explain this. It makes sense to me now. Thank you very much!

Iniciar sesión para comentar.

Más respuestas (0)

Categorías

Productos

Versión

R2022b

Etiquetas

Preguntada:

el 13 de Dic. de 2022

Comentada:

el 13 de Dic. de 2022

Community Treasure Hunt

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

Start Hunting!

Translated by