nlfilter: Choosing nested subfunctions? - matlab

The syntax for nlfilter in MATLAB is:
B = nlfilter(A, [m n], fun)
I am considering creating a M-File with several subfunctions to be called using test function here; i.e., I wanted a choice such that each time I can choose what subfunction gets called under fun.
% Main Function
function test
B = nlfilter(A, [m n], fun)
% Subfunction 1
function sub1
.......
% Subfunction 2
function sub2
.......
% Subfunction 3
function sub3
.......
Will it be possible to generalize fun in such a way that I can call either sub1 or sub2 or sub3 from test.
EDIT
My function:
function funct(subfn)
clc;
I = rand(11,11);
ld = input('Enter the lag = ') % prompt for lag distance
fh = {#dirvar,#diagvar};
feval(fh{subfn});
A = nlfilter(I, [7 7], subfn);
% Subfunction
function [h] = dirvar(I)
c = (size(I)+1)/2
EW = I(c(1),c(2):end)
h = length(EW) - ld
end
% Subfunction
function [h] = diagvar(I)
c = (size(I)+1)/2
NE = diag(I(c(1):-1:1,c(2):end))
h = length(NE) - ld
end
end
When I run funct(1) now this is the output with error:
Enter the lag = 1
ld =
1
??? Input argument "I" is undefined.
Error in ==> funct>dirvar at 12
c = (size(I)+1)/2
Error in ==> funct at 6
feval(fh{subfn});
I am puzzled as to what is the problem now?

If you know the name of the subfunction, you can use str2func:
Change the test function to accept a string which holds the subfunction name:
function test (subfunNm)
And call nlfilter like this:
B = nlfilter(A, [m n], str2func (subfunNm));
Now you can call test:
test ('sub1')
etc.
EDIT
In the case of nested functions, you can hold a cell array of the function handles, and pass in an index (instead of a string):
function test(fnInd)
fh = {#f1,#f2,#f3};
feval(fh{fnInd});
function f1
disp('f1')
end
function f2
disp('f2')
end
function f3
disp('f3')
end
end
And call it using test (1) etc.

Take a look at str2func and/or function handles.
I'd personally stay away from strings to pass functions, but you might just need to use that.

Related

How to write a different handle objective function in MATLAB?

I have a function with multiple outputs, let's assume them as different objective function f1 and function f2. How could I write the two handling functions for the two objectives?
function [f1,f2] = myfunc(x)
f1=x^2;
f2=sqrt(x);
end
I gave a try
[obj1,obj2] = #(x)myfunc(x)
Make f1 and f2 function handles in myfunc() as follows:
function [f1, f2] = myfunc()
f1 = #(x) x^2;
f2 = #(x) sqrt(x);
end
Then you can call them from your main script/command window as:
[obj1,obj2] = myfunc();
x = 2; % just to test the output
obj1(x);
obj2(x);

Forwarding varargout in matlab non-verbosely

I have a matlab function like:
function [f, fdx] = twice(x)
f = x * 2;
if nargout > 1
fdx = 2;
end
end
I want to call this function from another function, keeping the optional second-argument semantics. However, this is messy:
function [g, gdx] = twiceplusinverse(x)
% this starts to get messy if the arguments to double are long
if nargout > 1
[f, fdx] = twice(x);
else
f = double(x)
end
g = f + 1/x;
if narargout > 1
gdx = fdx + -1/x^2;
end
end
How can I avoid duplicating every function call that has multiple return values? What's a way to write the following that doesn't violate DRY?
if nargout > 1
[f, fda, fdb, fdc] = longfunction(some_func_producing_a(), b, another_func_for_c());
else
f = longfunction(somefunc_like_above(), b, another_func_for_c());
end
You can use varargout as the output of your function and then use a comma-separated list to assign the outputs of the other function. Since you use 1:nargout as the indices in the comma-separated list, the number of output arguments requested from your function will be passed onto the other function automatically.
function varargout = myfunc(x)
[varargout{1:nargout}] = other_func(x);
end

Matlab coder fzero function

I am trying to convert a MATLAB code to C code using "MATLAB Coder", but anonymous functions are not allowed.
How can I convert for example an fzero function as
myfun = #(x,c) cos(c*x); % parameterized function
c = 2; % parameter
fun = #(x) myfun(x,c); % function of x alone
x = fzero(fun,0.1)
into a normal function, for instance, to convert the whole code to C.
You have "anonymous" functions, not "undefined" functions, just to clear up the terminology.
To convert the following to a named function:
myfun = #(x,c) cos(c*x); % parameterized function
write this:
function result = myfun(x,c)
result = cos(c*x);
end
For the second function, write this:
function result = myfun2(x)
c = 2;
result = cos(c*x);
end
Finally, call fzero like this:
x = fzero(#myfun2, 0.1);

Undefined function or variable

I have a simple function as below:
function dz = statespace(t,z)
dz = A*z + B*k*z
end
My main script is :
clear all;close all;format short;clc;
% step 1 -- input system parameters
% structure data
M1 = 1; M2= 1; M3= 1; %Lumped Mass(Tons)
M= diag([M1,M2,M3]);
k(1)= 980; k(2)= 980; k(3)= 980; %Stiffness Coefficient(KN/M)
K = zeros(3,3);
for i=1:2
K(i,i)=k(i)+k(i+1);
end
K(3,3)=k(3);
for i=1:2
K(i,i+1)=-k(i+1);
end
for i=2:3
K(i,i-1)=-k(i);
end %Stiffness Matrix(KN/M)
c(1)= 1.407; c(2)= 1.407; c(3)= 1.407; %Damping Coefficient(KN.sec/M)
C = zeros(3,3);
for i=1:2
C(i,i)=c(i)+c(i+1);
end
C(3,3)=c(3);
for i=1:2
C(i,i+1)=-c(i+1);
end
for i=2:3
C(i,i-1)=-c(i);
end %Damping Matrix(KN.sec/M)
A = [zeros(3) eye(3);-inv(M)*K -inv(M)*C]
H = [1;0;0]
B = [0;0;0;inv(M)*H]
k = [-1 -1 -1 -1 -1 -1]
t = 0:0.004:10;
[t,z] = ode45(statespace,t);
When I run my main script it comes with following error:
Undefined function or variable 'A'.
Error in statespace (line 2)
dz = A*z + B*k*z
As you can see I defined A in main script. Why this problem happening?
There multiple things wrong with your code. First, you need to supply the values of A and B to your function but as you are invoking it (incorrectly without the # and additional parameter y0 as I commented below) in the toolbox ode45, you have to keep just two parameters so you cannot supply A and B as additional parameters. If you define A and B within your function or share them via global variables you will get further. However, as noted below the definitions don't seem to be correct as A * z and B * k * z don't have the same dimensions. z is a scalar so B * k needs to be same size and shape as A which currently it is not.
Edit from:
As Jubobs suggested change your function's parameters to include A, B and k. Also you don't need t as it is never used in the function. So:
function dz = statespace(A, B, k, z)
dz = A*z + B*k*z
end
As others have pointed out, A, B and k are not defined in the function workspace, so you either need to define them again (ugly, not recommended), declare them as global variables (slightly better, but still not good practice), or pass them as arguments to your function (the better solution). However, because you then want to use the function with ode45, you need to be a bit careful with how you do it:
function dz = statespace(t,z,A,B,k)
dz = A*z + B*k*z
end
and then the call to ode45 would like this:
[t,z] = ode45(#(t,z)statespace(t,z,A,B,k),[0 Tf],z0); % where Tf is your final time and z0 your initial conditions
See Error using ode45 and deval for a similar problem.

Call function inside another function

I have a function
function toto(a,b)
[out,~] = evalc(a)
% here I would like to call another function
myFunc(x,y,file);
end
How could I pass this function as args to toto function as sometimes I want to call toto(a,b) and some other times toto(a,b,#()myFunc(x,y) ?
(Answer before question edit: assumes fixed number of inputs to toto)
If you want to call an arbitrary function from within function toto: first define a handle to that function:
f = #myFunc;
and then pass that handle as input argument to toto, so that you can use it within toto:
function toto(a,b,f)
[out,~] = evalc(a)
f(x,y,file); %// call function whose handle is f
end
Define your function with an input to pass a function handle:
function toto(a,b,fun)
...
% You must know how many inputs and outputs to expect
% but nargin and nargout do work for function handles
% so you can handle different cases if needed.
[y1,y2,...] = fun(x1,x2,...);
...
Call the function and pass in a handle to the function:
toto(a,b,#FunName)
Or:
FunHandle = #FunName;
toto(a,b,FunHandle)
You can pass in additional parameters by using an anonymous function:
Param = 'FileName';
AnonFunHandle = #(x1,x2)FunName(x1,x2,Param);
toto(a,b,AnonFunHandle)
If you want to be able to use both the toto(a,b) and toto(a,b,f) or similar function calls, you need to use varargin and nargin (and their output counterparts). Here is a very basic example; it ignores any more than two outputs or any more than three inputs, and does not do any input checking etc.
function [vargout] = toto(a,b,varargin)
if nargin >2
func = vargin{1};
fout = func(a,b);
else
fout = [] % if no third argument is given returns empty
end
if nargout > 0
varargout{1} = a+b;
end
if nargout > 1
varargout{2} = fout;
end
end
So for example you can call this as x = toto(2,3) (returns x = 5), [x y] = toto(2,3) (returns x = 5, y = []), [x y] = toto(2,3,#(x,y)(x*y)) (returns x = 5, y = 6).