In Matlab some functions adapt their output to the number of output variables in the call. For example I can do:
A=[[1 2 3];[4 5 6]];
s=size(A);
And I get
s=[2, 3];
But if I want to handle independently width and height I can do:
[h, w]=size(A);
And I get:
h=2;
w=3;
Now, if I have a function that always output a vector of let's say 3 elements. Is there a way to assign each element to a different variable?
I mean to avoid an scenery like this:
pos=getPosition();
X=pos(1);
Y=pos(2);
Z=pos(3);
I hope I have explained what I mean.
I've had the same problem. Mostly with functions handling coordinates as in your example. My solution was to create the following function:
function varargout = dealOneByOne(vector)
% Assign each column of vector to each variable on the output variables
%
for i=1:size(vector,2)
varargout{i}=vector(:,i);
end
end
Then you can just do
[X,Y,Z]=dealOneByOne(getPosition());
I'm not aware of a simpler way to do it.
Let's define a test function as follows:
function x = test()
x = [1 2 3];
end
Given the function above, this is what I would normally perform in order to split the output array into many distinct variables:
out = num2cell(test());
[a,b,c] = deal(out{:});
A wrapper function can be defined in order to avoid spreading the above assignment into multiple lines:
[a,b,c] = vout_num(test());
function varargout = vout_num(x)
C = num2cell(x);
varargout = C(:).';
end
In your example, the wrapper function would be used as follows:
[X,Y,Z] = vout_num(getPosition());
Related
Is there any natural way to define a MATLAB function with multiple outputs that cannot or are inappropriate to "stack" into a matrix? For example, what if I want a function f that returns a 3x3 matrix A and a 4x4 matrix B?
I'm really surprised that this would even be an issue in MATLAB. Because in Python, all we need to do is return A, B which returns a tuple of the two. However it seems that MATLAB doesn't quite support the idea of containers. As a non-elegant workaround, I can use a struct to put the two pieces of data in, and the function goes something like:
function re = f(x)
%f: returns two dimensional-inconsistent matrices A and B
% function body as follows
....
A = ...;
B = ...;
% put data into the struct 're'
re.A = A;
re.B = B;
end
Apart from possible performance issues, this approach looks very unnatural and clumsy. Is there any better approach?
In MATLAB you can return any number of outputs with this syntax:
function [A,B] = f(x)
A = ...;
B = ...;
end
that is an even elegant solution than tuples used in python.
You can even control the behavior with the number of inputs and outputs (nargin and nargout) and discard outputs with a tilde. More information here.
I cannot think of a more elegant syntax.
Usually when having several outputs, one should declare the function as follows:
function [out1, out2, ... , outN] = funcName(in1,...,inM)
...
end
MATLAB also allows you to alter the behavior of your function based on the amount of requested inputs/outputs via the nargin/nargout functions, respectively (you can think of this as a form of overloading).
For example, you can specify as one of the inputs an array indicating which outputs you want the function to give, then populate the varargout cell array accordingly:
function varargout = funcName(in1,...,whichOut)
...
for indO = 1:numel(whichOut)
switch whichOut{indO}
case 'out1'
varargout{indO} = out1;
case 'out2'
... etc
case 'out6'
varargout{indO} = out6;
end
end
then call it using [out6, out1] = funcName(inp, {'out6','out1'});
See also varargin.
I find it impossible to write MATLAB code without creating a huge number of superfluous, single-use variables.
For example, suppose function foo returns three column vectors of exactly the same size. Say:
function [a, b, c] = foo(n)
a = rand(n, 1);
b = rand(n, 1);
c = rand(n, 1);
end
Now, suppose that bar is a function that expect as imput a cell array of size (1, 3).
function result = bar(triplet)
[x, y, z] = triplet{:};
result = x + y + z;
end
If I want to pass the results of foo(5), I can do it by creating three otherwise-useless variables:
[x, y, z] = foo(5);
result = bar({x, y, z});
Is there some function baz that would allow me to replace the two lines above with
result = bar(baz(foo(5)));
?
NB: the functions foo and bar above are meant only as examples. They're supposed to represent functions over which I have no control. IOW, modifying them is not an option.
You can replace the three variables by a cell array using a comma-separated list:
vars = cell(1,3); % initiallize cell array with as many elements as outputs of foo
[vars{:}] = foo(5); % comma-separated list: each cell acts as a variable that
% receives an output of foo
result = bar(vars);
Not possible. baz in baz(foo(5)) will only take the first output of foo, the other two would be ignored. The plain two-line variant is not that awkward. And this is not a common situation. You don't generally work with cell arrays where normal numerical arrays would do.
You could of course just write your own wrapper for foo that returns whatever you need (i.e. containing similar two lines), in case you need to use it frequently.
As nirvana-msu said, it is not possible to do the task without creating temporary variables. But it is possible to handle it within a function and even with varargin and varargout. Inspired by this answer on my question, you can define and use the following function:
function varargout = redirect(F1, F2, count, list, varargin)
output = cell(1, count);
[output{:}] = F2(varargin{:});
varargout = cell(1, max(nargout, 1));
[varargout{:}] = F1(output(list));
end
For instance, in your example you can write result = redirect(#bar, #foo, 3, [1:3], 5);
The issue is you are converting the cell triplet{} into an array[], so a conversion is the method you want. Although this method will perform the inverse transformation, I know of no method that will perform the transformation you want, likely due to the relative complexity of the cell data structure. You may have some luck further digging into the API.
EDIT: EBH kindly pointed out this method, which does what you are looking for.
EDIT2: The above method will not perform the action OP asked for. Leaving this up because the API often has great solutions that are hidden by bad names.
Say I want to create an anonymous function from a m-file-function that returns two outputs. Is it possible to set up the anonymous function such that it only returns the second output from the m-file-function?
Example: ttest2 returns two outputs, t/f and a probability. If I want to use the t-test with cellfun, I might only be interested in collecting the probabilities, i.e. I'd like to write something like this
probabilities = cellfun(#(u,v)ttest2(u,v)%take only second output%,cellArray1,cellArray2)
There's no way I know of within the expression of the anonymous function to have it select which output to return from a function with multiple possible output arguments. However, you can return multiple outputs when you evaluate the anonymous function. Here's an example using the function MAX:
>> data = [1 3 2 5 4]; %# Sample data
>> fcn = #(x) max(x); %# An anonymous function with multiple possible outputs
>> [maxValue,maxIndex] = fcn(data) %# Get two outputs when evaluating fcn
maxValue =
5 %# The maximum value (output 1 from max)
maxIndex =
4 %# The index of the maximum value (output 2 from max)
Also, the best way to handle the specific example you give above is to actually just use the function handle #ttest2 as the input to CELLFUN, then get the multiple outputs from CELLFUN itself:
[junk,probabilities] = cellfun(#ttest2,cellArray1,cellArray2);
On newer versions of MATLAB, you can replace the variable junk with ~ to ignore the first output argument.
One way to do this is to define the function:
function varargout = getOutput(func,outputNo,varargin)
varargout = cell(max(outputNo),1);
[varargout{:}] = func(varargin{:});
varargout = varargout(outputNo);
end
and then getOutput(#ttest2,2,u,v) gives only the p-value.
To use it in a cellfun you would need to run:
probabilities = cellfun(#(u,v)getOutput(#ttest2,2,u,v)...
This eliminates the need to write a wrapper every time, but then you have to make sure this function is always in the path.
I have an m-file function with 4 outputs. I would like to define an anonymous function that has the same inputs, but only produces 2 of the four outputs. Is this possible?
AFAIK, you can't do this with just an inline anonymous function, because that Matlab syntax doesn't provide a way of capturing and indexing in to multiple outputs of a function in a single expression. But you can write a couple reusable helper functions that do so, and then define anonymous functions using them.
Let's say your four argout function is named "f4".
function varargout = f4(x)
%F4 Dummy function that returns 4 argouts holding identifying indexes
varargout = num2cell(1:4);
Here's a reusable helper function that remaps outputs of a function call.
function varargout = callandmap(fcn, ix, varargin)
%CALLANDMAP Call a function and rearrange its output arguments
tmp = cell(1,max(ix)); % Capture up to the last argout used
[tmp{:}] = fcn(varargin{:}); % Call the original function
varargout = tmp(ix); % Remap the outputs
Now you can make anonymous, argout-remapping functions like this. Here, g holds an anonymous function that takes the same inputs as your original function, but just returns 2 of its original 4 outputs.
>> g = #(varargin) callandmap(#f4, [2 4], varargin{:})
g =
#(varargin)callandmap(#f4,[2,4],varargin{:})
>> [a,b] = g('dummy') % gets argouts 2 and 4 from original f4() function
a =
2
b =
4
>>
Using varargin allows you to omit trailing arguments when the resulting function handle is called. If you know all argins will always be provided, you can use named argins for readability if you want.
You can get even fancier and do this with a closure.
function fcn = mapargout(fcnIn, ixArgout)
%MAPARGOUT Create wrapper function that selects or reorders argouts
%
% fcn = argoutselector(fcnIn, ixArgout)
%
% Wraps a given function handle in a function that rearranges its argouts.
% This uses closures so it may have performance impacts.
%
% FcnIn is a function handle to wrap.
%
% IxArgout is a list of indexes in to the original functions argout list
% that should be used as the outputs of the new function.
%
% Returns a function handle to a new function.
fcn = #extractor;
function varargout = extractor(varargin)
n = max(ixArgout);
tmp = cell(1,n);
% Call the wrapped function, capturing all the original argouts
[tmp{:}] = fcnIn(varargin{:});
% And then select the ones you want
varargout = tmp(ixArgout);
end
end
This results in simpler code for creating the anonymous function. And you could compose it with other function wrapper calls.
>> g = mapargout(#f4, [2 4])
g =
#mapargout/extractor
>> [a,b] = g('dummy')
a =
2
b =
4
>>
But closures can be tricky to work with in Matlab and may have performance implications. The callandmap approach is probably preferable unless you need the extra power.
If the two outputs are #1 and #2, everything is fine, and you don't have to worry about the other two outputs.
If the two outputs are any two others, you have two options
(1) Create a wrapper function with two outputs (note that in newer versions of Matlab you can replace the unused outputs dummy by ~.
function [out1,out2] = wrapperFunction(in1,in2,in3)
[dummy,out1,dummy,out2] = mainFunction(in1,in2,in3);
(2) Add another input variable that allows you to switch your function's behavior
function varargout = mainFunction(in1,in2,in3,outputSwitch)
%# make output switch optional
if nargin < 4 || isempty(outputSwitch)
outputSwitch = 0;
end
%# calculation here that creates out1-4
if outputSwitch
%# the special case where we only want outputs 2 and 4
varargout = {out2,out4};
else
%# return all four outputs
varargout = {out1,out2,out3,out4}
end
Then you can create the anonymous function as usual.
Say I want to create an anonymous function from a m-file-function that returns two outputs. Is it possible to set up the anonymous function such that it only returns the second output from the m-file-function?
Example: ttest2 returns two outputs, t/f and a probability. If I want to use the t-test with cellfun, I might only be interested in collecting the probabilities, i.e. I'd like to write something like this
probabilities = cellfun(#(u,v)ttest2(u,v)%take only second output%,cellArray1,cellArray2)
There's no way I know of within the expression of the anonymous function to have it select which output to return from a function with multiple possible output arguments. However, you can return multiple outputs when you evaluate the anonymous function. Here's an example using the function MAX:
>> data = [1 3 2 5 4]; %# Sample data
>> fcn = #(x) max(x); %# An anonymous function with multiple possible outputs
>> [maxValue,maxIndex] = fcn(data) %# Get two outputs when evaluating fcn
maxValue =
5 %# The maximum value (output 1 from max)
maxIndex =
4 %# The index of the maximum value (output 2 from max)
Also, the best way to handle the specific example you give above is to actually just use the function handle #ttest2 as the input to CELLFUN, then get the multiple outputs from CELLFUN itself:
[junk,probabilities] = cellfun(#ttest2,cellArray1,cellArray2);
On newer versions of MATLAB, you can replace the variable junk with ~ to ignore the first output argument.
One way to do this is to define the function:
function varargout = getOutput(func,outputNo,varargin)
varargout = cell(max(outputNo),1);
[varargout{:}] = func(varargin{:});
varargout = varargout(outputNo);
end
and then getOutput(#ttest2,2,u,v) gives only the p-value.
To use it in a cellfun you would need to run:
probabilities = cellfun(#(u,v)getOutput(#ttest2,2,u,v)...
This eliminates the need to write a wrapper every time, but then you have to make sure this function is always in the path.