matlabfunctionfunction-handle

How do I call a function handle with an vector rather than a list of arguments?


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.


Solution

  • 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!