What do I want?
I am looking for a way to detect all points in my code where a specific function is called.
Why do I want it?
Some examples:
Some output comes out sorted or randomized, and I want to know where this happens
I am considering to change/overload a function and want to know in which part of my code this could have impact
What have I tried?
I tried placing a breakpoint in the file that was called. This only works for non builtin functions which are called from short running code that always executes everything.
I tried 'find files', this way I can easily find direct calls to sort but it is not so easy to find a call to sort invoked by unique for example.
I have tried depfun, it tells me:
whether something will be called
from where non-builtin functions will be called
I thought of overloading the builtin function, but feels like a last resort for me as I am afraid to make a mess. | Edit: Also it probably won't help due to function precedence.
The question
What is the best way to track all potential (in)direct function calls from a specific function to a specific (built-in)function.
I don't exactly understand your use case, but I guess most of the information you want can be obtained using dbstack, which gives you the call-stack of all the parent functions calling a certain function. I think the easiest way is to overload built-in functions something like this (I tried to overload min):
function varargout = min(varargin)
% print info before function call
disp('Wrapped function called with inputs:')
disp(varargin)
[stack,I] = dbstack();
disp('Call stack:')
for i=1:length(stack)
fprintf('level %i: called from line %i in file %s\n', ...
i, stack(i).line, stack(i).file);
end
% call original function
[varargout{1:nargout}] = builtin('min', varargin{:});
% print info after function call
disp('Result of wrapped function:')
disp(varargout)
I tried to test this, but I could not make it work unfortunately, matlab keeps on using the original function, even after playing a lot with addpath. Not sure what I did wrong there, but I hope this gets you started ...
Built-in functions take precedence over functions in local folder or in path. There are two ways you can overload a built-in for direct calls from your own code. By putting your function in a private folder under the same directory where your other MATLAB functions are. This is easier if you are not already using private folder. You can rename your private folder once you are done investigating.
Another way is to use packages and importing them. You put all your override functions in a folder (e.g. +do_not_use). Then in the function where you suspect built-in calls are made add the line "import do_not_use.*;". This will make calls go to the functions in +do_not_use directory first. Once you are done checking you can use "clear import" to clear all imports. This is not easy to use if you have too many functions and do not know in which function you need to add import.
In addition to this, for each of the function you need to follow Bas Swinckels answer for the function body.
Function precedence order.
Those two methods does not work for indirect calls which are not from your own code. For indirect calls I can only think of one way where you create your own class based on built-in type. For example, if you work only on double precision types, you need to create your own class which inherits from double and override the methods you want to detect. Then pass this class as input to your code. Your code should work fine (assuming you are not using class(x) to decide code paths) since the new class should behave like a double data type. This option will not work if your output data is not created from your input data. See subclassing built-in types.
Did you try depfun?
The doc shows results similar to the ones you request.
doc depfun:
...
[list, builtins, classes, prob_files, prob_sym, eval_strings, called_from, java_classes] = depfun('fun') creates additional cell arrays or structure arrays containing information about any problems with the depfun search and about where the functions in list are invoked. The additional outputs are ...
Looks to me you could just filter the results for your function.
Though need to warn you - usually it takes forever to analyze code.
Related
I have a struct with relative sophisticated data trees. for example:
class.data.head{1}.data2
What I wish to get is a variable named data2_link to link with address class.data.head{1}.data2, so that:
(1) if there is any change on class.data.head{1}.data2, it will automatically reflected to data2_link as well, and vise versa.
(2) I do not have to type the long name to access the data at class.data.head{1}.data2.
Thanks!
Matlab does not support references. The only exception is handle which allows references to objects.
To use it, data2 must be an object with superclass handle, then you could simply write:
data2_link=class.data.head{1}.data2
Note that object oriented matlab significantly slows down your code unless you use Matlab 2015b or newer.
There is an extremely discouraged way to do it. you can create a function handle that evaluates the desired expression:
data2_link = #() evalin('caller', 'class.data.head{1}.data2')
Now every time you need that expression just call it using
>> data2_link()
The extra parentheses are necessary to invoke the function defined by function handle.
Just got another idea, you could use subsref to access it and subassign to write. It is not really what I would call a reference because you still need S, but it probably comes as close to it as possible without using OOP.
S=substruct('.','data','.','head','{}',{1},'.','data2')
%previous line is the same as: S=struct('type',{'.','.','{}','.'},'subs',{'data','head',{1},'data2'})
f=subsref(class,S)
I am having a problem with the findpeaks function, this function is in the signal processing toolbox and also the program has another version of it (user defined function). I need to call the on in the signal processing toolbox not the user defined one, also I can't rename the user defined function for many reasons. Can anyone help me in calling the toolbox function.
The precedence order used by MATLAB is described in their help pages. It states that functions in the current folder (9.) are preferred over functions elsewhere in the path (10.). Then, the first appearance of the function in the path is chosen. This allows for a number of possible solutions:
1. cd to folder
A very simple method is simply to change the current workspace directory to the folder of the function you need to call, i.e. cd either to the place where your user-defined function is, or cd to the toolbox path. Note: This is rather inelegant, but probably sometimes the simplest solution.
2. Reorder path
As mentioned, MATLAB choses the first occurence of the function in the path. You can thus re-sort the path variable, so the folder where your user-defined function is, appears last. The path variable can be viewed and manipulated using the path function. Note: Then you can only call the toolbox function. Otherwise you'd have to resort the path again.
3. Function handles
If you need to be able to call both functions, it can be useful to create a function handle for both versions. For that, you have to cd into the folders where the functions are defined and create a new handle there:
cd('path/to/userdefined/function')
userFindPeaks = #findpeaks;
cd('path/to/MATLAB/installation/toolbox/signal/signal')
toolboxFindPeaks = #findpeaks;
You can then call the functions using feval.
Of course, as Adriaan mentions in the comments, it is best not to use the names of already defined functions for your own functions or for variable names.
I just came here looking for the same thing... I ended up using builtin.
https://uk.mathworks.com/help/matlab/ref/builtin.html
[y1,...,yn] = builtin(function,x1,...,xn)
#arr_sea actually posted a link in one of the folded comments which uses this function in a different context.
I have a large project going with 40+ functions and it's just increasing every day. Often times I reference a function multiple times from different scripts. Every once in a while, I'll find that I need to edit a function for one script, and then I realize that it's possible that I want that function to stay the same for another script. Obviously this in itself is no problem; I can just write a new function. But sometimes I don't remember if I've referenced that function anywhere else in my larger folder containing all my scripts!
Is there a way in MATLAB to somehow find a count of how many times a function is used within a folder? If so, is there a way to track where it's being referenced from? Thanks in advance =).
For this I typically use the find files funcionality (found in the menu on top of your screen) with the 'contains' option. Especially if your function name does not match common variable names this works very well.
Just search in the entire matlab path, or in the specific directory for something like myFun( and you will see all the places where it is called. In the worst case you will also find some places where it is not called.
MATLAB provides support for dependency tracking using the depfun function. depfun tells you which other functions are required to run a given function.
What you're asking is the opposite problem: Which functions require a given function?
Using depfun, you can do a reverse lookup. Here's a quick example:
function result = invdepfun(allFunctions, lookFor)
% Return all functions that depend on a given function
%
% Example: invdepfun({'myfun1', 'myfun2', 'myfun3'}, 'myfun4') returns all of
% 'myfun1', 'myfun2', 'myfun3' that use 'myfun4'.
filename = which(lookFor);
result = {};
for i = 1 : numel(allFunctions)
deps = depfun(allFunctions{i}, '-quiet');
if any(strcmpi(deps, filename))
result{end + 1} = allFunctions{i};
end
end
end
You can use various other MATLAB functions (which, dir, etc.) to autmatically compile a list of all your functions to pass to invdepfun as the first argument.
See also this post on File Exchange.
I don't know of any builtin Matlab functionality that does this, so you probably have to write some function to do this for you.
You could use the DIRWALK function from Matlab FileExchange to crawl your project folder and look into all Matlab files (use the what command) searching for your function name.
I have been reading someone else's matlab code and I don't know how the code structured. I mean I would like to know the hierarchy of functions, which function uses which function. I am reading the code to figure that out but its taking a lot of time.
So is there any other way I can see this hierarchy without reading the whole thing? To be honest it is starting to get confusing. Maybe MatLab has a built in function for that! I found this:
How can I generate a list of function dependencies in MATLAB?
but this doesn't seem to be helpful!
The MATLAB profiler will show you what functions are called by your code (and much more information to boot) and allow you to click through the hierarchy of function calls. You can either call profile on and then run your code, then call profile off and profile viewer, or you can simply call profile viewer and type a single line of code to run in the edit box at the top.
Use the dependency report provided in MATLAB:
http://www.mathworks.co.uk/help/matlab/matlab_prog/identify-dependencies.html
There are also some tools on the File Exchange, such as fdep.
No idea about a function to show visible or depended-upon functions. However the basic rules are:
1) Only the first function in a .m file (normally has to have the same name as the file itself) is visible outside that file.
2) Any function can see any top level (see 1.) function if the file is in the matlab path. Matlab can show you the path so you know where it's hunting.
3) The order of the path is important, the first instance of a function called foo found in the path will be called. Obviously the current directory is at the top of the path.
3) All functions in a given file can see all other functions in that file.
That's the basics. No doubt there are other rules, and possibly exceptions to this. But that understanding generally serves me well.
Obviously the easiest way to work out which function is being called is to click on it in the editor and open it.
One thing I do is simply place in each function at the beginning fprintf("inside function <name>/n"); and at the end of the function fprintf("leaving function <name>/n"); where <name> is the name of the function.
This will give you a very specific list of which function is being called by which function (based on the order that they appear). Another thing like this would be to place fprintf("function <name1> calling function <name2>/n"); so you can be more explicit about which function is being called by which one.
Let us say that I have a Matlab function and I change its signature (i.e. add parameter). As Matlab does not 'compile' is there an easy way to determine which other functions do not use the right signature (i.e. submits the additional parameter). I do not want to determine this at runtime (i.e. get an error message) or have to do text searches. Hope this makes sense. Any feedback would be very much appreciated. Many thanks.
If I understand you correctly, you want to change a function's signature and find all functions/scripts/classes that call it in the "old" way, and change it to the "new" way.
You also indicated you don't want to do it at runtime, or do text searches, but there is no way to detect "incorrect" calls at "parse-time", so I'm afraid these demands leave no option at all to detect old function calls...
What I would do in that case is temporarily add a few lines to the new function:
function myFunc(param1, param2, newParam) % <-- the NEW signature
if nargin == 2
clc, error('old call detected.'); end
and then run the main script/function/whatever in which this function resides. You'll get one error for each time something calls the function incorrectly, along with the error stack in the Matlab command window.
It is then a matter of clicking on the link in the bottom of the error stack, correct the function call, and repeat from the top until no more errors occur.
Don't forget to remove these lines when you're done, or better, replace the word error with warning just to capture anything that was missed.
Better yet: if you're on linux, a text search would be a matter of
$ grep -l 'myFunc(.*,.*); *.m'
which will list all the files having the "incorrect" call. That's not too difficult I'd say...You can probably do a similar thing with the standard windows search, but I can't test that right now.
This is more or less what the dependency report was invented for. Using that tool, you can find what functions/scripts call your altered function. Then it is just a question of manually inspecting every occurrence.
However, I'd advise to make your changes to the function signature such that backwards compatibility is maintained. You can do so by specifying default values for new parameters and/or issuing a warning in those scenarios. That way, your code will run, and you will get run-time hints of deprecated code (which is more or less a necessary evil in interpreted/dynamic languages).
For many dynamic languages (and MATLAB specifically) it is generally impossible to fully inspect the code without the interpreter executing the code. Just imagine the following piece of code:
x = magic(10);
In general, you'd say that the magic function is called. However, magic could map to a totally different function. This could be done in ways that are invisible to a static analysis tool (such as the dependency report): e.g. eval('magic = 1:100;');.
The only way is to go through your whole code base, either inspecting every occurrence manually (which can be found easily with a text search) or by running a test that fully covers your code base.
edit:
There is however a way to access intermediate outputs of the MATLAB parser. This can be accessed using the undocumented and unsupported mtree function (which can be called like this: t = mtree(file, '-file'); for every file in your code base). Using the resulting structure you might be able to find calls with a certain amount of parameters.