I have some parameters changing size on every loop iteration in main.m. I have placed the preallocations in another script called preallocation.m.
When the preallocations is placed in another script, I get a warning from Matlab for every parameter in the main script about concidering preallocating for improved speed.
Is there a way to remove these warnings? If I add another parameter that needs preallocating and forget to preallocate, I'd like to get a warning for that parameter.
I'd be tempted to make your preallocation script a function. Then you could write something like
[myvar1,myvar2,myvar3] = preallocate();
This would allow you to see all preallocated variables at a glance and would also keep mlint quiet.
In my MATLAB version (R2014b) this is done by right-clicking on the variable that has the squiggly red line onder it, and then selection the option Suppress "The variable myVar appears to...". You can then choose to suppress this single line, all warnings of this type in the entire file, or all warnings of this type in all files.
edit: if your MATLAB version does not have this context menu option, you can add %#ok<SAGROW> to the end of the offending line, like so:
someVar(ii+1) = someVar(ii) + someConstant; %#ok<SAGROW>
If you are hell-bent on not wanting these warnings and not using a preallocation function that returns many variables, you could also do the following:
function init = preallocate()
init.a = some stuff;
init.b = some stuff;
...
end
%% actual script
init = preallocate()
structvars(init); % using structvars from file exchange
structvars can be found here. Note that I haven't tried the package myself, so I am unsure as to how well it will work and how fast it is.
Related
In MATLAB, how do you tell where in the code a variable is getting output?
I have about 10K lines of MATLAB code with about 4 people working on it. Somewhere, someone has dumped a variable in a MATLAB script in the typical way:
foo
Unfortunately, I do not know what variable is getting output. And the output is cluttering out other more important outputs.
Any ideas?
p.s. Anyone ever try overwriting Standard.out? Since MATLAB and Java integration is so tight, would that work? A trick I've used in Java when faced with this problem is to replace Standard.out with my own version.
Ooh, I hate this too. I wish Matlab had a "dbstop if display" to stop on exactly this.
The mlint traversal from weiyin is a good idea. Mlint can't see dynamic code, though, such as arguments to eval() or string-valued figure handle callbacks. I've run in to output like this in callbacks like this, where update_table() returns something in some conditions.
uicontrol('Style','pushbutton', 'Callback','update_table')
You can "duck-punch" a method in to built-in types to give you a hook for dbstop. In a directory on your Matlab path, create a new directory named "#double", and make a #double/display.m file like this.
function display(varargin)
builtin('display', varargin{:});
Then you can do
dbstop in double/display at 2
and run your code. Now you'll be dropped in to the debugger whenever display is implicitly called by the omitted semicolon, including from dynamic code. Doing it for #double seems to cover char and cells as well. If it's a different type being displayed, you may have to experiment.
You could probably override the built-in disp() the same way. I think this would be analagous to a custom replacement for Java's System.out stream.
Needless to say, adding methods to built-in types is nonstandard, unsupported, very error-prone, and something to be very wary of outside a debugging session.
This is a typical pattern that mLint will help you find:
So, look on the right hand side of the editor for the orange lines. This will help you find not only this optimization, but many, many more. Notice also that your variable name is highlighted.
If you have a line such as:
foo = 2
and there is no ";" on the end, then the output will be dumped to the screen with the variable name appearing first:
foo =
2
In this case, you should search the file for the string "foo =" and find the line missing a ";".
If you are seeing output with no variable name appearing, then the output is probably being dumped to the screen using either the DISP or FPRINTF function. Searching the file for "disp" or "fprintf" should help you find where the data is being displayed.
If you are seeing output with the variable name "ans" appearing, this is a case when a computation is being done, not being put in a variable, and is missing a ';' at the end of the line, such as:
size(foo)
In general, this is a bad practice for displaying what's going on in the code, since (as you have found out) it can be hard to find where these have been placed in a large piece of code. In this case, the easiest way to find the offending line is to use MLINT, as other answers have suggested.
I like the idea of "dbstop if display", however this is not a dbstop option that i know of.
If all else fails, there is still hope. Mlint is a good idea, but if there are many thousands of lines and many functions, then you may never find the offender. Worse, if this code has been sloppily written, there will be zillions of mlint flags that appear. How will you narrow it down?
A solution is to display your way there. I would overload the display function. Only temporarily, but this will work. If the output is being dumped to the command line as
ans =
stuff
or as
foo =
stuff
Then it has been written out with display. If it is coming out as just
stuff
then disp is the culprit. Why does it matter? Overload the offender. Create a new directory in some directory that is on top of your MATLAB search path, called #double (assuming that the output is a double variable. If it is character, then you will need an #char directory.) Do NOT put the #double directory itself on the MATLAB search path, just put it in some directory that is on your path.
Inside this directory, put a new m-file called disp.m or display.m, depending upon your determination of what has done the command line output. The contents of the m-file will be a call to the function builtin, which will allow you to then call the builtin version of disp or display on the input.
Now, set a debugging point inside the new function. Every time output is generated to the screen, this function will be called. If there are multiple events, you may need to use the debugger to allow processing to proceed until the offender has been trapped. Eventually, this process will trap the offensive line. Remember, you are in the debugger! Use the debugger to determine which function called disp, and where. You can step out of disp or display, or just look at the contents of dbstack to see what has happened.
When all is done and the problem repaired, delete this extra directory, and the disp/display function you put in it.
You could run mlint as a function and interpret the results.
>> I = mlint('filename','-struct');
>> isErrorMessage = arrayfun(#(S)strcmp(S.message,...
'Terminate statement with semicolon to suppress output (in functions).'),I);
>>I(isErrorMessage ).line
This will only find missing semicolons in that single file. So this would have to be run on a list of files (functions) that are called from some main function.
If you wanted to find calls to disp() or fprintf() you would need to read in the text of the file and use regular expresions to find the calls.
Note: If you are using a script instead of a function you will need to change the above message to read: 'Terminate statement with semicolon to suppress output (in scripts).'
Andrew Janke's overloading is a very useful tip
the only other thing is instead of using dbstop I find the following works better, for the simple reason that putting a stop in display.m will cause execution to pause, every time display.m is called, even if nothing is written.
This way, the stop will only be triggered when display is called to write a non null string, and you won't have to step through a potentially very large number of useless display calls
function display(varargin)
builtin('display', varargin{:});
if isempty(varargin{1})==0
keyboard
end
A foolproof way of locating such things is to iteratively step through the code in the debugger observing the output. This would proceed as follows:
Add a break point at the first line of the highest level script/function which produces the undesired output. Run the function/script.
step over the lines (not stepping in) until you see the undesired output.
When you find the line/function which produces the output, either fix it, if it's in this file, or open the subfunction/script which is producing the output. Remove the break point from the higher level function, and put a break point in the first line of the lower-level function. Repeat from step 1 until the line producing the output is located.
Although a pain, you will find the line relatively quickly this way unless you have huge functions/scripts, which is bad practice anyway. If the scripts are like this you could use a sort of partitioning approach to locate the line in the function in a similar manner. This would involve putting a break point at the start, then one half way though and noting which half of the function produces the output, then halving again and so on until the line is located.
I had this problem with much smaller code and it's a bugger, so even though the OP found their solution, I'll post a small cheat I learned.
1) In the Matlab command prompt, turn on 'more'.
more on
2) Resize the prompt-y/terminal-y part of the window to a mere line of text in height.
3) Run the code. It will stop wherever it needed to print, as there isn't the space to print it ( more is blocking on a [space] or [down] press ).
4) Press [ctrl]-[C] to kill your program at the spot where it couldn't print.
5) Return your prompt-y area to normal size. Starting at the top of trace, click on the clickable bits in the red text. These are your potential culprits. (Of course, you may need to have pressed [down], etc, to pass parts where the code was actually intended to print things.)
You'll need to traverse all your m-files (probably using a recursive function, or unix('find -type f -iname *.m') ). Call mlint on each filename:
r = mlint(filename);
r will be a (possibly empty) structure with a message field. Look for the message that starts with "Terminate statement with semicolon to suppress output".
When plotting a set of figures using a for loop, for example:
for ei=1:length(E),
hnds(ei) = plot(1:nP, avgR(ei,:), [clrStr(ei),'-'] );
end
There is a (the famous) warning in the code for the hnds(ei) variable:
The variable hnds(ei) appears to change size on every loop iteration.
Consider pre-allocating for speed.
But when I try to pre-allocate the variable:
hnds = zeros(1,length(E));
there is another warning for this new line and in the details for pre-allocation it says:
Suggested Action: Avoid preallocating memory to a variable assigned to
the output of another function.
Is there any way to remove this warning, or should just ignore it?
Just put special %#ok comment at the end of the line and it will disable all warnings associated with this line:
hnds = zeros(1,length(E)); %#ok
You can also use special %#ok<specific1, ...> comment to disable only very specific warnings but not other ones. Check this link for furhter details.
You can try iterate in reverse order to avoid the warning:
for ei=length(E):-1:1,
hnds(ei) = plot(1:nP, avgR(ei,:), [clrStr(ei),'-'] );
end
In this case you do not need to pre-allocate (i.e., no hnds = zeros(1,length(E));).
By iterating in reverse order, the array size hnds is determined in the first iteration and stays fixed throughout the iterations.
See this thread for more information.
You can deactivate it in Preferences:
(Matlab 2013b)
I think it is not possible to suppress this certain warning in this certain loop of a single script, just global.
It's different for warnings which are displayed in the command window, they can be suppressed individually.
Edit: I was wrong.
Let's say you are some new programmer and you do something like...
%...la da da
%...programming away
if such && such
clear = 1;
else
clear = 0;
end
or in some other way, you assign the variable clear a value.
Is there some way to "clear" clear?
clearvars doesn't work. Clicking the workspace variable and manually clicking delete does work, but I think it's cheating.
This will do it:
builtin('clear','clear')
Note: Keep in mind to avoid such operations to keep code clarity. Only do overwrite when it is the exact action you want to take place. Otherwise it may cause future bugs if you forgot (or if another person uses your code and didn't realize it) that you have the clear (or any other) function overwritten. You could easily name this variable as doClear for example.
Any name, even builtin and feval can be overriden. In such case, you can use function handles instead to force MALTAB into interpreting a statement as a function call:
clear = str2func('clear');
clear('clear')
Obviously, str2func can also be overrriden! :) however, there exists a similar solution (inspired by Loren's article), which is creating a separate m-file that does the same thing:
function clearclear()
assignin('caller', 'clear', #clear);
Calling this function in the main workspace should allow you to do clear('clear') safely.
The second solution takes advantage of the fact that the m-file doesn't "see" the variable clear in the main workspace, and therefore can access the actual handle of the clear function properly.
A non intuitive way is
clear = rand(1000,500,700);
pack
This produces the following warning:
Warning: Variable 'clear' cannot be saved to a MAT-file whose version
is older than 7.3. To save this variable, use the -v7.3 switch.
Skipping...
It also suffers from the same issue that you can assign pack to be a variable.
Interesting problem! I found it surprisingly hard to find an ways to do this programatically (besides the one suggested by #TryHard)
Here is the I have come up with though it is a bit more powerfull than clear:
!matlab &
exit
Note that if you want to type this in the command line at once, you need to use a shift+enter in between.
Suppose I'm using the MATLAB IDE and happen to have some very large objects in my workspace (e.g. arrays of 500k+ elements). Now, suppose that I stupidly and accidentally double click on one of these very large variables, which triggers a load to the array editor. Unfortunately, with arrays this big, MATLAB just hangs.
I've tried CTRL+C, CTRL+BREAK, CTRL+D, but none seem able to interrupt the behavior of the IDE. I know I can force matlab to quit, but reading all of those variables into the workspace in the first place takes a lot of time, and I may have unsaved changes in an editor window, etc.
The variable editor is launched using the command openvar. To solve your problem you can take advantage of a Matlab quirk that causes functions to be masked by variables with the same name. For example if you create a variable named plot the plot() function stops working.
The solution, although hackish, is to simply create an empty variable named openvar. Then anytime attempt to open the variable editor will fail because the function openvar is being hidden by the variable.
If you want to use the variable editor again simple call clear openvar to delete the variable and the function will be unmasked.
I found a way, but it's not the best, it requires a change of path and back once to get a handle to the original openvar
function openvar(name,array)
persistent org_openvar
if isempty(org_openvar)
curdir=pwd;
cd(fullfile(matlabroot,'toolbox/matlab/codetools'));
org_openvar = #openvar;
cd(curdir);
end
if numel(array)>1e5
if strcmp(questdlg(sprintf('Opening ''%s'' which has %d elements.\n\nAre you sure? This is gonna take a while!',name,numel(array)), ...
'Variable editor','Yes','Cancel','Cancel') , 'Yes')
org_openvar(name,array)
end
else
org_openvar(name,array)
end
end
getting that handle is the biggest problem, calling it is just fine. If openvar would be built in, you could use the function builtin:
builtin('openvar',name,array)
but this is unfortunately not the case :(
str2func in combination with the complete path also doesn't work, at least I don't get it to work...
As described here, I created my own figure.m which nicely overloads the built-in figure command. Now, whenever I start MATLAB I get the warning
Warning: Function C:\somepath\figure.m has
the same name as a MATLAB builtin. We
suggest you rename the function to
avoid a potential name conflict.
Is there any way to deactivate this warning, given that it is desired behavior in my case?
You might say that I should call my function differently instead of overloading, but I do feel for my development system this overloading is the right way to go...
Update
As mentioned by Aabaz you can globally turn off this warning using
warning off MATLAB:dispatcher:nameConflict
which needs to go at the beginning of matlabrc.m (before the path is set). However, I would still be interested in a solution which could specificially remove this error message for overloading figure.m (or some self-defined list of functions) instead of for all functions. I guess I'm asking a bit too much here ;-) ?
I cannot seem to replicate this warning with my Matlab version (R2008b) but anyway If you did not already try it you should look into the functions lastwarn and warning that allow you to identify and turn off this warning.
PS: the warning eventually came for some reason and I was able to use lastwarn and warning to turn it off.
>>[msgstr msgid]=lastwarn;
>>disp(msgid);
MATLAB:dispatcher:nameConflict
>>warning('off',msgid);
I should add that you should turn it off at startup for this to be effective between different sessions of Matlab.
I just ran into this problem on MATLAB R2014b where I also wanted to override figure. I think this is the closest solution to your updated question (3.5 years later...).
I think using the "dirty" trick from your comment is actually the cleanest, if done smartly as it doesn't require you to change matlabrc.m and can suppress the warning for only functions that you want to override built-in ones.
Put all your default overrides in a folder that is not on your permanent MATLAB path. I keep mine in ~/Documents/MATLAB/overrides on my Mac. I have e.g. ~/Documents/MATLAB/overrides/figure.m
Use startup.m to add overrides to your path with the warning turned off, and then turn it back on:
warning off MATLAB:dispatcher:nameConflict
addpath('/Users/victor/Documents/MATLAB/overrides');
warning on MATLAB:dispatcher:nameConflict
Not sure if tilde expansion works with addpath so I write the full path out.
Doing it this way suppresses the warning for me selectively only for the stuff that gets loaded from overrides. You can, of course, be even more selective with your folder naming. It also means I don't have to change anything in my MATLAB system files so it's localized to my user account and persistent across upgrades (for good or bad; monkey patch responsibly).
To access the built-in figure from my override, I have to cd there temporarily (as otherwise the override will simply call it self). So figure.m would look like this:
function fig = figure(varargin)
% Call original figure function
old = pwd;
cd(fullfile(matlabroot, 'toolbox', 'matlab', 'graphics', ''));
fig = figure(varargin{:});
cd(old);
% ...
% Do dirty override magic
end
I can't comment yet, so I'll just expand the answer given by vicvicvic further here. The general process stays the same, however it has some further fine tunings.
Put your override-function figure.m in a folder which is not on your current MATLAB path, e.g. /users/heidelberg/.matlab/_overload. For me, tilde expansion is supported, but I would not rely on it. However, you could also put it in a subfolder of a MATLAB startup script (see below).
Use startup.m to add your override folder to the path. To avoid the warning, make sure it is turned off, and then restore its original state
% save the current state while switching it off
warningState = warning('off', 'MATLAB:dispatcher:nameConflict');
addpath('/users/heidelberg/.matlab/_overload');
% restore the saved state
warning(warningState);
% cleanup
clear('warningState');
The difference here is that if e.g. your administrator set the warning to be off anyway, you won't accidentally switch it back on.
In your implementation of figure, at some point you will probably have to call the builtin version. vicvicvic suggested a cd to the directory, however there also is the MATLAB function builtin, which does that job for you:
function fig = figure(varargin)
% overload function
% call builtin figure
varargout = cell(1, nargout);
[varargout{:}] = builtin('figure', varargin{:});
% do you magic here
% ...
end
Also, use varargout and nargout to preserve for an arbitrary number of output arguments (might be irrelevant here and now, but for other functions or future releases it might be important).
Annotation
A method I prefer is to have a subfolder in the directory where my startup.m file is stored, called e.g. _overload. For me this is /users/timm/Documents/MATLAB/_overload. To easily add this folder, use the following script:
File /users/timm/Documents/MATLAB/startup.m
% extract the current directory (pwd can fail if started elsewhere)
[currentPath, ~, ~] = fileparts(mfilename('fullpath'));
% add the path, compare above
warningState = warning('off', 'MATLAB:dispatcher:nameConflict');
addpath([currentPath, filesep(), '_overload']);
warning(warningState);
% cleanup
clear('currentPath', 'warningState');
Adding a directory that contains the function overload to the search path will display the warning whenever a function in that directory is edited and saved, no matter if the directory is added in startup.m or not.
A simple way to solve this is to put overloading functions in a package. Then import the package in startup. No need to mess with warnings.