Is certain matlab-routine used in matlab script? - matlab

I am running a big m-file that I didn't write myself and that depends on certain subfunctions. I want to know if anywhere in all nested functions a particular function (in my case the function eig.m (to calculate eigenvalues) ) is used.
Is there a quick way to do this?
kind regards,
Koen

You can use the semi-documented function getcallinfo (see Yair Altman's blog for more information about it):
getcallinfo
Returns called functions and their first and last lines
This function is unsupported and might change or be removed without
notice in a future version.
General use of getcallinfo
Let's create an example script which contains subfunctions (this works in Matlab R2016b or newer) and save it as 'filename.m'. The procedure also works if there are nested functions, or if the main file is a function instead of a script.
x = input('');
y = find(x);
z = f(norm(x));
disp(z)
function u = f(v)
u = -log2(v) + log2(pi);
end
Then:
>> g = getcallinfo('filename.m');
gives you a nested struct array with interesting information, including function calls. The first entry, g(1), refers to the main file. There may be further entries for subfunctions or nested functions. In this case, g(2) refers to subfunction f.
>> g(1).calls.fcnCalls
ans =
struct with fields:
names: {'input' 'find' 'norm' 'disp' 'log2' 'log2' 'pi'}
lines: [1 2 3 4 6 6 6]
>> g(1).calls.innerCalls
ans =
struct with fields:
names: {'f'}
lines: 3
>> g(2).calls.fcnCalls
ans =
struct with fields:
names: {'log2' 'log2' 'pi'}
lines: [6 6 6]
>> g(2).calls.innerCalls
ans =
struct with fields:
names: {1×0 cell}
lines: [1×0 double]
Other fields of g give further details, such as name
>> g(1).name
ans =
filename
>> g(2).name
ans =
f
or type
>> g(1).type
ans =
Script with no properties.
>> g(2).type
ans =
subfunction
How to determine if a given function is used anywhere in the file
Obtain g as explained above, and then look for the desired function name in all calls.fcnCalls.names fields of g:
g = getcallinfo('filename.m');
sought_function = 'log2'; % or 'eig' in your case
t = arrayfun(#(x) x.calls.fcnCalls.names, g, 'UniformOutput', false);
% collect all names of called functions. Gives a cell array of cell arrays
% of strings (character vectors)
t = [t{:}]; % de-nest: concatenate into cell array of strings
result = any(strcmp(t, sought_function)); % compare with sought function name

One option to check by hand would be to use the profiler.
I'm using a 2014 Matlab, i cannot run the previous example. However, as far as i saw on the previous answer by Luis Mendo, it shows similar information but in a webpage style.

Basically, I would also suggest you use the profiler, which will list all called functions.
But to give you an alternative, if you are looking for just a single function (please see the disclaimer), you can utilize that functions in the current folder have precedence. Thus, say that you want to check if you use a function called jacobianest, then you create a new function in your folder called jacobianest.m with e.g.
function jacobianest(args)
error('jacobianest is being used')
end
then if the program terminates with that error, you are using jacobianest.
Disclaimer 1: This works only for the non-build-in functions. In the sense that if you type edit *name of function* and only comments come up, you cannot use this strategy. If the code itself shows up, you can.

Related

What does the code '[~, width ] = size(I);'mean?I can't undestand '~'especially [duplicate]

Is it possible to get the 'nth' return value from a function without having to create dummy variables for all n-1 return values before it?
Let's say, I have the following function in MATLAB:
function [a,b,c,d] = func()
a = 1;
b = 2;
c = 3;
d = 4;
Now suppose, I'm only interested in the third return value. This can be accomplished by creating one dummy variable:
[dummy, dummy, variableThatIWillUse, dummy] = func;
clear dummy;
But I think this is kind of ugly. I would think that you might be able to do something like one of the following things, but you can't:
[_, _, variableThatIWillUse, _] = func;
[, , variableThatIWillUse, ] = func;
variableThatIWillUse = func(3);
variableThatIWillUse = func()(3);
Are there any elegant ways to do this that do work?
So far, the best solution is to simply use the variableThatIWillUse as a dummy variable. This saves me from having to create a real dummy variable that pollutes the work-space (or that I would need to clear). In short: the solution is to use the variableThatIWillUse for every return value up until the interesting one. Return values after can simply be ignored:
[variableThatIWillUse, variableThatIWillUse, variableThatIWillUse] = func;
I still think this is very ugly code.
With MATLAB Version 7.9 (R2009b) you can use a ~, e.g.,
[~, ~, variableThatIWillUse] = myFunction();
Note that the , isn't optional. Just typing [~ ~ var] will not work, and will throw an error.
See the release notes for details.
This is somewhat of a hack, but it works:
First a quick example function:
Func3 = #() deal(1,2,3);
[a,b,c]=Func3();
% yields a=1, b=2, c=3
Now the key here is that if you use a variable twice on the left-hand side of a multiple-expression assignment, an earlier assignment is clobbered by the later assignment:
[b,b,c]=Func3();
% yields b=2, c=3
[c,c,c]=Func3();
% yields c=3
(Just to check, I also verified that this technique works with [mu,mu,mu]=polyfit(x,y,n) if all you care about from polyfit is the third argument.)
There's a better approach; see ManWithSleeve's answer instead.
If you wish to use a style where a variable will be left to fall into the bit bucket, then a reasonable alternative is
[ans, ans, variableThatIWillUse] = myfun(inputs);
ans is of course the default junk variable for MATLAB, getting overwritten often in the course of a session.
While I do like the new trick that MATLAB now allows, using a ~ to designate an ignored return variable, this is a problem for backwards compatibility, in that users of older releases will be unable to use your code.
I generally avoid using new things like that until at least a few MATLAB releases have been issued to ensure there will be very few users left in the lurch. For example, even now I find people are still using an old enough MATLAB release that they cannot use anonymous functions.
Here's another option you can use. First make a cell array to capture all the outputs (you can use the NARGOUT function to determine how many outputs a given function returns):
a = cell(1,3); % For capturing 3 outputs
% OR...
a = cell(1,nargout(#func)); % For capturing all outputs from "func"
Then call the function as follows:
[a{:}] = func();
Then simply remove the element from a that you want, and overwrite a:
a = a{3}; % Get the third output
I wrote a kth out function:
function kth = kthout(k, ffnc, varargin)
% kthout: take the kth varargout from a func call %FOLDUP
%
% kth = kthout(k, ffnc, varargin)
%
% input:
% k which varargout to get
% ffnc function to call;
% varargin passed to ffnc;
% output:
% kth the kth argout;
[outargs{1:k}] = feval(ffnc, varargin{:});
kth = outargs{k};
end %function
You can then call
val_i_want = kthout(3, #myfunc, func_input_1, func_input_2);
You could also wrap up the function like:
func_i_want = #(varargin)(kthout(3, #myfunc,varargin{:})); % Assuming you want the third output.
After which you use
val_i_want = func_i_want(func_input_1, func_input_2);
Note that there is overhead associated with using anonymous functions like this, and this is not something I would do in code that would be called thousands of times.
In MATLAB 2010a, I found a neat way of doing what you are asking for.
It is simply to use the character "~" (without the quotes of course) as your dummy variable (as many as you want when returning multiple parameters). This also works for input parameters to functions if the functions are designed to handle missing data.
I don't know if this existed in previous versions, but I just came across it recently.
You can make a function (or anonymous function) that only returns selected outputs, e.g.
select = #(a,b) a(b);
Then you can call your function like this:
select(func,2);
select(func,1:3);
Or you can assign the output to a variable:
output(1,2:4) = select(func,1:3);
I don't see any reason not to use ans(n). Like this:
size(rand([5 10 20 40]));
b = ans(2);
It gives b = 10, and this way would be compatible with all MATLAB versions. Note that size() here is just used to represent any function that has multiple return variables.
Furthermore, this works to get the second output argument when you don't know how many arguments there will be! Whereas, if you do this:
[~, b] = size(a);
Then b = 8000! (You need to end with ~, to catch more arguments!)

How to assign each element/column of output to a different variable

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());

How to force MATLAB to return all values in a nested function call?

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.

Skipping outputs with anonymous function in MATLAB

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.

How to elegantly ignore some return values of a MATLAB function

Is it possible to get the 'nth' return value from a function without having to create dummy variables for all n-1 return values before it?
Let's say, I have the following function in MATLAB:
function [a,b,c,d] = func()
a = 1;
b = 2;
c = 3;
d = 4;
Now suppose, I'm only interested in the third return value. This can be accomplished by creating one dummy variable:
[dummy, dummy, variableThatIWillUse, dummy] = func;
clear dummy;
But I think this is kind of ugly. I would think that you might be able to do something like one of the following things, but you can't:
[_, _, variableThatIWillUse, _] = func;
[, , variableThatIWillUse, ] = func;
variableThatIWillUse = func(3);
variableThatIWillUse = func()(3);
Are there any elegant ways to do this that do work?
So far, the best solution is to simply use the variableThatIWillUse as a dummy variable. This saves me from having to create a real dummy variable that pollutes the work-space (or that I would need to clear). In short: the solution is to use the variableThatIWillUse for every return value up until the interesting one. Return values after can simply be ignored:
[variableThatIWillUse, variableThatIWillUse, variableThatIWillUse] = func;
I still think this is very ugly code.
With MATLAB Version 7.9 (R2009b) you can use a ~, e.g.,
[~, ~, variableThatIWillUse] = myFunction();
Note that the , isn't optional. Just typing [~ ~ var] will not work, and will throw an error.
See the release notes for details.
This is somewhat of a hack, but it works:
First a quick example function:
Func3 = #() deal(1,2,3);
[a,b,c]=Func3();
% yields a=1, b=2, c=3
Now the key here is that if you use a variable twice on the left-hand side of a multiple-expression assignment, an earlier assignment is clobbered by the later assignment:
[b,b,c]=Func3();
% yields b=2, c=3
[c,c,c]=Func3();
% yields c=3
(Just to check, I also verified that this technique works with [mu,mu,mu]=polyfit(x,y,n) if all you care about from polyfit is the third argument.)
There's a better approach; see ManWithSleeve's answer instead.
If you wish to use a style where a variable will be left to fall into the bit bucket, then a reasonable alternative is
[ans, ans, variableThatIWillUse] = myfun(inputs);
ans is of course the default junk variable for MATLAB, getting overwritten often in the course of a session.
While I do like the new trick that MATLAB now allows, using a ~ to designate an ignored return variable, this is a problem for backwards compatibility, in that users of older releases will be unable to use your code.
I generally avoid using new things like that until at least a few MATLAB releases have been issued to ensure there will be very few users left in the lurch. For example, even now I find people are still using an old enough MATLAB release that they cannot use anonymous functions.
Here's another option you can use. First make a cell array to capture all the outputs (you can use the NARGOUT function to determine how many outputs a given function returns):
a = cell(1,3); % For capturing 3 outputs
% OR...
a = cell(1,nargout(#func)); % For capturing all outputs from "func"
Then call the function as follows:
[a{:}] = func();
Then simply remove the element from a that you want, and overwrite a:
a = a{3}; % Get the third output
I wrote a kth out function:
function kth = kthout(k, ffnc, varargin)
% kthout: take the kth varargout from a func call %FOLDUP
%
% kth = kthout(k, ffnc, varargin)
%
% input:
% k which varargout to get
% ffnc function to call;
% varargin passed to ffnc;
% output:
% kth the kth argout;
[outargs{1:k}] = feval(ffnc, varargin{:});
kth = outargs{k};
end %function
You can then call
val_i_want = kthout(3, #myfunc, func_input_1, func_input_2);
You could also wrap up the function like:
func_i_want = #(varargin)(kthout(3, #myfunc,varargin{:})); % Assuming you want the third output.
After which you use
val_i_want = func_i_want(func_input_1, func_input_2);
Note that there is overhead associated with using anonymous functions like this, and this is not something I would do in code that would be called thousands of times.
In MATLAB 2010a, I found a neat way of doing what you are asking for.
It is simply to use the character "~" (without the quotes of course) as your dummy variable (as many as you want when returning multiple parameters). This also works for input parameters to functions if the functions are designed to handle missing data.
I don't know if this existed in previous versions, but I just came across it recently.
You can make a function (or anonymous function) that only returns selected outputs, e.g.
select = #(a,b) a(b);
Then you can call your function like this:
select(func,2);
select(func,1:3);
Or you can assign the output to a variable:
output(1,2:4) = select(func,1:3);
I don't see any reason not to use ans(n). Like this:
size(rand([5 10 20 40]));
b = ans(2);
It gives b = 10, and this way would be compatible with all MATLAB versions. Note that size() here is just used to represent any function that has multiple return variables.
Furthermore, this works to get the second output argument when you don't know how many arguments there will be! Whereas, if you do this:
[~, b] = size(a);
Then b = 8000! (You need to end with ~, to catch more arguments!)