Can I access a local variable of a function without outputting it? - matlab

I have a function in MATALB that looks like the following:
function [a, b] = SumIt(I1, I2)
a = sum(I1);
b = sum(I2);
c = sum(I1/I2);
end
In the command window, I run the function but I cannot access the c variable. I know that I can do something like this [a, b, c] = SumIt(I1, I2) and access c variable. Can I access the variable c without outputting it?
The issue is that I have many outputs that are useless but I need to access them. How can I do this?
I tried with global but I got the same error.
function [a, b] = SumIt(I1, I2)
global c;
a = sum(I1);
b = sum(I2);
c = sum(I1/I2);
end
>> [a, b] = SumIt([1 4 6], [1 2 3]);
>> c
Undefined function or variable 'c'.

The only way that this can be done is to have a function script that also declares SumIt as an additional function and also declaring c to be global outside of the scope of SumIt. Consider the following test function shown below:
function [] = test_func()
global c;
function [a, b] = SumIt(I1, I2)
a = sum(I1);
b = sum(I2);
c = sum(I1/I2);
end
[t1, t2] = SumIt(6, 3);
disp(['t1 = ' num2str(t1)]);
disp(['t2 = ' num2str(t2)]);
disp(['c = ' num2str(c)]);
end
I have created a test function called test_func where we declare c to be global, but it is outside of the scope of SumIt. After, I declare SumIt as a nested function, then try and call it with some example numbers. I then display the outputs of SumIt as well as c. Since I1 = 6, I2 = 3, we should get c = 2.
This is what I get when I run test_func:
>> test_func
t1 = 6
t2 = 3
c = 2
Minor note
It looks like I1 and I2 are vectors judging from the context of your use with sum. As such, you should probably consider using the element-by-element division operator ./ if what I am interpreting is correct. Are you trying to divide each element of I1 by I2 and then summing the result? If that's the case, you need to change your function such that it becomes:
function [a, b] = SumIt(I1, I2)
a = sum(I1);
b = sum(I2);
c = sum(I1./I2);
end

Related

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.
If I understand correctly, you are looking for a way to pass a variable number of input arguments to an anonymous function.
Take a look at this example:
anonymousFunction = #(varargin)(image(varargin{:}));
x = [5 8];
y = [3 6];
C = [0 2 4 6; 8 10 12 14; 16 18 20 22];
input = {C};
anonymousFunction(input{:});
input = {x,y,C};
anonymousFunction(input{:});
You can see in the example that a variable number of inputs is used for calling the anonymous function. Of course, this depends on the actual function that is using the arguments (in this case, image)
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!

Retrieve saved variable values from anonymous function

For example, taken from Matlab:
a = 1.3;
b = .2;
c = 30;
parabola = #(x) a*x.^2 + b*x + c;
parabola can be called even if a, b, c are removed from the workspace. The explanation is:
Because a, b, and c are available at the time you create parabola, the function handle includes those values. The values persist within the function handle even if you clear the variables:
After an anonymous function like parabola is created, how do I later retrieve or see the variables stored inside it?
You can use the functions function to get information about an anonymous function including the internal workspace in which those variables are defined.
a = 1.3;
b = .2;
c = 30;
parabola = #(x) a*x.^2 + b*x + c;
clear a b c
F = functions(parabola);
variables = F.workspace{1};
%// variables =
%//
%// a: 1.3
%// b: 0.2
%// c: 30
The workspace contains a struct with a field for each variable that is contained within the function handle's workspace.

How to pass a multi-output return to a function?

If I have a multi-output code
function [a b] = foo()
a = 1;
b = 2;
end
Can we pass foo()'s result to another function directly,
function test(a)
a
end
test(foo());
It prints only 1.
I am not sure, in test, how we can destruct its argument. It is not an array.
Do we have to do?
[x, y] = foo();
test(x, y);
No, there is no other way.
One variation of this is using a cell arrays and comma-separated lists. Example:
C = cell(1,2);
[C{:}] = foo();
bar(C{:})
you can reuse the above code for any number of input/output arguments, just replace 2 above with the actual number.
C = cell(1,n);
[C{:}] = foo(); % equivalent to [C{1},C{2},...,C{n}] = foo()
bar(C{:}) % equivalent to bar(C{1},C{2},...,C{n})

How does the lu( ) function decide what to return?

Let A be the following matrix:
1 3
2 4
if I call the lu( ) function and save the return values like this:
[L, U] = lu(A);
MATLAB returns L, U such that L * U = A:
>> L * U
ans =
1 3
2 4
While when I save the return values like this:
[L, U, P] = lu(A);
L * U is not equal to A:
>> L * U
ans =
2 4
1 3
because lu( ) returns L, U, P such that L * U = P * A
My questions:
How can the lu( ) function know how many return parameters I have asked for?
Can I replicate this behavior in my code?
You can use the nargout function to detect how many output arguments have been requested.
In addition, you can use varargout to fill your argument list appropriately.
For example:
function varargout = myfun(a,b)
switch nargout
case 1
varargout{1} = a;
case 2
varargout{1} = b;
varargout{2} = a;
end
end
When called with one output argument, the first (and only) output will be a. When called with two, the first will be b, the second a.
You can also use nargoutchk (or in older versions nargchk) to assert that the number of output arguments requested is within specified limits.
lu does something similar to this, but is implemented in compiled C rather than MATLAB.
Yes, this can be replicated using varargout. Similarly you can use varargin if you want variable number of inputs.
function varargout = my_fun(a,b,c);
varargout{1} = b;
varargout{2} = c;
varargout{3} = a;
end
Now, this function can be called
x = my_fun(1,2,3)
x = 2
[x, y] = my_fun(1,2,3)
x = 2
y = 3
[x, y, z] = my_fun(1,2,3)
x = 2
y = 3
z = 1
As Sam Roberts points out, this does not help you create a function that behaves differently for different numbers of outputs. If that's what you want, you should check out nargout in combination with a switch-statement. Similarly, you can use nargin if you want to alter the behavior depending on the number of input variables. Please check out Sam Roberts' answer to see how this can be done.

Using inline function with constant arguments in MATLAB

This is a part of my code.
clear all;
clc;
p = 50;
t = [-6 : 0.01 : 6];
f = inline('(t+2).*sin(t)', 't')
v = inline('3*f(p*t+2)','t','f','p')
plot(t,f(t));
v(t,f,p);
figure;
plot(t,v(t,f,p));
Here I have two questions.
Why I have to pass p into the function v even though p is a constant which has already declared ?
How I can get an expression for v completely in terms of t as 3*[(50*t+2)*sin(50*t+2)] or in its simplified form ?
Update
This is an update for the second question
Let
f(x) = 1 + x - x^2
g(x) = sin(x)
If I give f(g(x)), I wanna get the output in words, like this
f(g(x)) = (cos(X))^2 + sin(x)
not in numerical value. Is there any function capable to do that?
1) Why do I have to pass p to v even though p is a constant which has already been declared?
Well, a MATLAB's inline function object has an eval wrapper, so the only variables in its scope are those which were automatically captured from the expression or explicitly specified.
In other words, if you want v to recognize p, you have no other option but declaring it when creating the inline object and passing it to v explicitly. The same goes for f as well!
2) How I can get an expression for v completely in terms of t as 3*[(50*t+2)*sin(50*t+2)] or in its simplified form?
Use anonymous functions, like Shai suggested. They are more powerful, more elegant and much faster. For instance:
v = #(t)(3*(50*t+2)*sin(50*t+2))
Note that if you use a name, which is already in use by a variable, as an argument, the anonymous function will treat it as an argument first. It does see other variables in the scope, so doing something like g = #(x)(x + p) is also possible.
EDIT #1:
Here's another example, this time a function of a function:
x = 1:5;
f = #(x)(x .^ 3); %// Here x is a local variable, not as defined above
g = #(x)(x + 2); %// Here x is also a local variable
result = f(g(x));
or alternatively define yet another function that implements that:
h = #(x)f(g(x)); %// Same result as h = #(x)((x + 2) .^ 3)
result = h(x);
The output should be the same.
EDIT #2:
If you want to make an anonymous function out of the expression string, concatenate the '#(x)' (or the correct anonymous header, as you see fit) to the beginning and apply eval, for example:
expr = '(x + 2) .^ 3';
f = eval(['#(x)', expr]) %// Same result as f = #(x)((x + 2) .^ 3)
Note that you can also do char(f) to convert it back into a string, but you'll have to manually get rid of the '#(...)' part.
EDIT #3:
If you're looking for a different solution, you can explore the Symbolic Toolbox. For example, try:
syms x
f(x) = x + 2
g(x) = x ^ 3
or can also use sym, like so:
f(x) = sym('x + 2');
g(x) = sym('x ^ 3');
Use subs to substitute values and evaluate the symbolic expression.
How about using anonymous functions:
p = 50;
t = -6:0.01:6;
f = #(x) (x+2).*sin(x);
v = #(x) 3*f(p*x+2);
figure;
subplot(1,2,1); plot( t, f(t) ); title('f(t)');
subplot(1,2,2); plot( t, v(t) ); title('v(t)');
Is this what you wanted?
Adding a constant into an inline can be done during its definition.
Instead of
p = 50;
v = inline('3*f(p*t+2)','t','f','p')
You can write
p = 50;
v = inline( sprintf('3*f(%f*t+2)', p), 't','f')