I was wondering how to call a function handle with an vector of inputs - rather than the list of aguments.
So if I have a function handle which is defined: (I guess it will be clear that I am working on fitting functions here)
fitFunctionHandle = @(a1, wG1, x1,a2, wG2, x2, c, x)(FitGaussianFn(x, [a1, 0, wG1, x1]) +FitGaussianFn(x, [a2, 0, wG2, x2]) + c
And I have an vector of inputs to hand to it
a1Init = 1
wG1Init = 2
x1Init = 3
a2Init = 4
wG2Init = 5
x2Init = 6
a2Init = 7
x = 8
%startPoint = [a1Init, wG1, x1,a2, wG2, x2, c]
inputArray = [a1Init, wG1, x1,a2, wG2, x2, c, x]
How do I call it with the vector startPoint as the input. If I try (for example)
>> fitFunctionHandle(inputArray)
I get an error:
Not enough input arguments.
That makes sense since it is expecting 8 inputs rather than a 8 element vector - but I'm wondering whether there is a way of calling it like that. I think for example in python you can convert an array to a list or something.
I'm aware that I could simplify things in this example case where I have a list of known inputs so I could just do:
fitFunctionHandle(a1Init, wG1, x1,a2, wG2, x2, c, x)
or
fitFunctionHandle(inputArray(1),inputArray(2),inputArray(3,inputArray(4), inputArray(5), inputArray(6),inputArray(7),inputArray(8))
BUT! I guess I'm trying to allow for expansion where I don't know how many arguments there would be. For bonus points (again since I'm working on fitting functions) - It would be cool to know how to call it when x is a vector as well. I suspect that I would be doing something like
arrayfunc(fitFunctionHandle([startPoint,x]), xVector)
Thanks in advance for your help.
Regarding the varargin
, the general idea was already presented in UnbearableLightness' answer. I just wanted to address your specific case.
It seems, you want to have some dynamic linear combinations of your FitGaussianFn
calls with varying parameters, resulting in some complex function handle. For variable amount of terms, I would recommend to write a separate function to generate the final function handle. I made up a small toy example.
That's my fitFunctionHandle.m
function:
function h = fitFunctionHandle(varargin)
n = numel(varargin);
if (n < 2)
error('Not enough input arguments.');
end
% Last input argument is considered t
t = varargin{end};
h = @(x) 0;
for iArg = 1:n-1
a = varargin{iArg}(1);
b = varargin{iArg}(2);
h = @(x) h(x) + (a*sin(b*x+t));
end
end
Each input argument consists of two parameters, that form a sin
term. An additional shift parameter t
is always passed at last.
And, here's some test script:
% Set up parameters
a1 = 1; b1 = 1;
a2 = 2; b2 = 2;
a3 = 3; b3 = 3;
t = pi/16;
% Evaluation point
x = pi/4;
% Compare results with explicit function calls
h = fitFunctionHandle([a1, b1], t);
res = h(x)
cmp = sin(x+t)
h = fitFunctionHandle([a1, b1], [a2, b2], t);
res = h(x)
cmp = sin(x+t) + 2*sin(2*x+t)
h = fitFunctionHandle([a1, b1], [a2, b2], [a3, b3], t);
res = h(x)
cmp = sin(x+t) + 2*sin(2*x+t) + 3*sin(3*x+t)
You see, it doesn't matter, how many parameter vectors are passed.
The output reveals, that the passed function handles are correct:
res = 0.83147
cmp = 0.83147
res = 2.7930
cmp = 2.7930
res = 4.4598
cmp = 4.4598
Regarding your last question, let's see this test:
% Set up array of t parameters, and get set of function handles
t = [pi/16, pi/8, pi/4];
hh = arrayfun(@(x) fitFunctionHandle([a1, b1], x), t, 'UniformOutput', false);
% Compare results with explicit function calls
for iH = 1:numel(hh)
h = hh{iH};
res = h(x)
cmp = sin(x + t(iH))
end
Here, the t
, which is used for all sin
terms in fitFunctionHanle
, is a vector. The arrayfun
call will return a cell array of function handles. Again, the output shows comparable results:
res = 0.83147
cmp = 0.83147
res = 0.92388
cmp = 0.92388
res = 1
cmp = 1
Hope that helps!