matlab: different result in script and command window - matlab

When I execute my script, one of the lines of code sets a variable to a 2x2 array of zeros. If I set a breakpoint, highlight the line and execute it in the command window, it produces an integer (which it should).
The other line sets first_peak to 0, when it should be 667.
(I added the cast in an attempt to resolve the problem because matlab was complaining about the variable type. Of course it didn't work.)
I can't seem to create an MWE without one of my datafiles, so attached are screenshots.
in-script:
command window:
If an MWE were going to produce the error, this one should, but again, it doesn't. The peaks(peak_ndx+1) line would produce the aforementioned 2x2 array, and peaks(peak_ndx) would produce the 0 value.
clear
for ndx = 1 : 6
peaks = [667 911 1288 1719 2114 2363 3505 3718 4010 4372 4682 4867];
peak_ndx=(ndx - 1) * 2 + 1;
peaks(peak_ndx)
peaks(peak_ndx+1)
end

TL;DR
When you hover the mouse over a variable, it shows the value that the variable currently has in the workspace.
The answer lies in the first paragraph you wrote. As you have mentioned, "When I execute my script, one of the lines of code sets a variable to a 2x2 array of zeros.", therefore hovering over second_peak on the line second_peak = cast(peaks(peak_ndx+1), 'int32') shows you zeros. Note that you have put a breakpoint on this line and this line is not executed yet. When you execute that line (unpause/continue running from the breakpoint) or enter that in the command window, you get the desired result.
If you put second_peak on another line and put a breakpoint on that line. Then after the second_peak = cast(peaks(peak_ndx+1), 'int32') line is run and program execution is paused at the next breakpoint, you'll see 1x1 int32 911.
Here is a reproducible example for you:
second_peak = int32([0,0;0,0]); %initially the value that you had
second_peak = int32(911); %put a breakpoint here
second_peak %and also here
Also make it sure that you're not doing unnecessary preallocation here.
Read "A Common Misunderstanding in Array Preallocation" in Loren Shure's blog.

If a variable is declared with the same name as a function, the variable may mask the function in some contexts (such as the Command Window), but not in others, such as in a script.

Related

Matlab serial communication inconsistency

I want to control a Prior ProScan II controller and the fitting motorized stage with Matlab R2016b. Manual Tested with R2010b, got the same results. The relevant commands of the stage are VS(page 46), P(p.43), PS(p.44). In a plain terminal, immediately after the stage halts I can issue the P or PS command, returning the current position of the X and Y axes. If done in Matlab prompt, it MIGHT need a second or two to return the proper value, before that it returns 'R' - Probably not the ACK of the previous command as it is returned after init, without any R-ACKed commands issued before. When used in a script in a separate .m file, it can only return 'R'. My code in main.m is as follows:
%Opening serial port
s = serial('COM9');
set(s,'BaudRate',9600,'Terminator','CR'); %Note that CR will be concatenated to all commands
fopen(s);
s %print for debugging
t=1 %loop index
while true
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Here is code to mess with a joystick that works fine, using VS command
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if button(joy, 3) == 1 %Button3 of joystick should trigger position reading
fprintf(s,'vs,0,0'); %Halt joystick movement
pause(1) %Debouncing
fprintf(s,'p'); %Axe-pos reading command
fgets(s) %Reading the answer
end
%This way to increment follows the skipped parts and is required for timing
if mod(t, 100)==0
fprintf(s,'%s',Command);
t=1;
else
t=t+1;
end
If the segment in if..end is invoked from the Matlab prompt, it works fine in most cases.
>> s = openserial()
%properties as before, skipped to save space
>> fprintf(s,'ps');
>> fgets(s)
ans =
100000,100000
or
>> fprintf(s,'p');
>> fgets(s)
ans =
100000,100000,0
If I Ctrl+C out of the infinite loop but leave the serial open and issue
>> fprintf(s,'p');
>> fgets(s)
ans =
R
returns. Using fscanf() instead of fgets() yields the same results.
Is there any known bug of fprintf() or the ones mentioned above that could cause this? What could I do to succesfully and consistently read within a script? Thank you for any answers.
Solution was to force flush the serial input buffer, flushinput(s) before the line pause(1). For some reason, even fscanf() instead of fgets() didn't flush it. I still don't know why it worked fine outside the script but not within. Additionally, it also worked in a separate script.

Stop/pause MatLab execution for any underflow and overflow [duplicate]

Is it possible to add a customized dbstop condition to Matlab?
Recently I found myself with out of bounds values in multiple variables, one way to track down the first occurance of this would be to set a conditional breakpoint on each line where these values are updated. However, I hope there is an easier way to do this.
I have recently had to track down a NaN which was fairly trivial due to:
dbstop if naninf
Hence I hope that it is possible to get something like:
dbstop if anything outside myBound
or
dbstop if myVariable outside myBound
I would of course be willing to take the performance hit that one may expect.
If you use the editor, you can set a stop as normal, right-click on it, select "set/modify condition" and enter the condition (the stop will turn from red to yellow).
From command line, you can use
dbstop in file if expression
dbstop in file at location if expression
e.g.
dbstop in myFile at 200 if (~isempty(var) && var > 3)
as mentioned by #LuisMendo.
The second option may be more useful, since the first one seems to be only evaluated at the start of the file. In other words, it doesn't seem to be possible to have a similarly generic expression as dbstop if naninf that checks for certain values across an entire file.
The problem with using the form "DBSTOP in FILESPEC if EXPRESSION" of dbstop is that it sets a breakpoint only at the first line of the file. A solution is to use the form "DBSTOP in FILESPEC at LINENO if EXPRESSION" to set a breakpoint at each line.
Consider the following example script, saved on a file called testfile.m.
clear all
for m = 1:10;
k = 2*m
end
Say we want to stop if variable k exceeds the value 6. We first automatically set the breakpoints in all lines of this file:
file = 'testfile.m';
varname = 'k';
expression = 'k>6'; %// it should be 'exist(''k'')&&k>6', but that's added later
%// Determine number of lines of file:
fid = fopen('testfile.m');
cont = 1;
nlines = 0;
while cont
readline = fgetl(fid);
cont = ~isequal(readline,-1);
nlines = nlines + cont;
end
fclose(fid);
%// Set breakpoint at each line. We need eval for this
for n = 1:nlines
eval(['dbstop in ' file ' at ' num2str(n) ' if ( exist(''' varname...
''') && ( ' expression ' ) )'])
end
Now, after running the above (check that every line of testfile.m has a yellow breakpoint), run testfile and check values when it stops:
This is admittedly a little cumbersome if you have several variables or files. Also, I'm not sure how many simultaneous breakpoints Matlab supports (we are using one for each program line).
Thinking outside the box - you could write a class to hold your variable. There you could have a customized setter that will raise a warning if you violate boundaries. dbstop if warning should then be enough.

Customize dbstop in MATLAB

Is it possible to add a customized dbstop condition to Matlab?
Recently I found myself with out of bounds values in multiple variables, one way to track down the first occurance of this would be to set a conditional breakpoint on each line where these values are updated. However, I hope there is an easier way to do this.
I have recently had to track down a NaN which was fairly trivial due to:
dbstop if naninf
Hence I hope that it is possible to get something like:
dbstop if anything outside myBound
or
dbstop if myVariable outside myBound
I would of course be willing to take the performance hit that one may expect.
If you use the editor, you can set a stop as normal, right-click on it, select "set/modify condition" and enter the condition (the stop will turn from red to yellow).
From command line, you can use
dbstop in file if expression
dbstop in file at location if expression
e.g.
dbstop in myFile at 200 if (~isempty(var) && var > 3)
as mentioned by #LuisMendo.
The second option may be more useful, since the first one seems to be only evaluated at the start of the file. In other words, it doesn't seem to be possible to have a similarly generic expression as dbstop if naninf that checks for certain values across an entire file.
The problem with using the form "DBSTOP in FILESPEC if EXPRESSION" of dbstop is that it sets a breakpoint only at the first line of the file. A solution is to use the form "DBSTOP in FILESPEC at LINENO if EXPRESSION" to set a breakpoint at each line.
Consider the following example script, saved on a file called testfile.m.
clear all
for m = 1:10;
k = 2*m
end
Say we want to stop if variable k exceeds the value 6. We first automatically set the breakpoints in all lines of this file:
file = 'testfile.m';
varname = 'k';
expression = 'k>6'; %// it should be 'exist(''k'')&&k>6', but that's added later
%// Determine number of lines of file:
fid = fopen('testfile.m');
cont = 1;
nlines = 0;
while cont
readline = fgetl(fid);
cont = ~isequal(readline,-1);
nlines = nlines + cont;
end
fclose(fid);
%// Set breakpoint at each line. We need eval for this
for n = 1:nlines
eval(['dbstop in ' file ' at ' num2str(n) ' if ( exist(''' varname...
''') && ( ' expression ' ) )'])
end
Now, after running the above (check that every line of testfile.m has a yellow breakpoint), run testfile and check values when it stops:
This is admittedly a little cumbersome if you have several variables or files. Also, I'm not sure how many simultaneous breakpoints Matlab supports (we are using one for each program line).
Thinking outside the box - you could write a class to hold your variable. There you could have a customized setter that will raise a warning if you violate boundaries. dbstop if warning should then be enough.

Is there a way to automatically suppress Matlab from printing big matrices in command window?

Is there an option in matlab or a plugin/app or a trick such that if you are in an interactive command session, every time it would print out a matrix way too big for a human to look through, it redacts the output to either a warning of how big the matrix is or a summary (only a few rows and columns) of the matrix?
There are many times where I want to examine a matrix in the command window, but I didn't realize how big it was, so I accidentally printed the whole thing out. Or some place inside a function I did not code myself, someone missed a semicolon and I handed it a big matrix, and it dumps the whole thing in my command window.
It make sense that in 99.99% of the time, people do not intend to print a million row matrix in their interactive command window, right? It completely spams their scroll buffer and removes all useful information that you had on screen before.
So it makes much more sense for matlab to automatically assume that the user in interactive sessions want to output a summary of a big matrix, instead of dumping the whole thing into the command window. There should at least be such an option in the settings.
One possibility is to overload the display function, which is called automatically when you enter an expression that is not terminated by ;. For example, if you put the following function in a folder called "#double" anywhere on your MATLAB path, the default display behavior will be overridden for double arrays (this is based on Mohsen Nosratinia's display.m for displaying matrix dimensions):
% #double/display.m
function display(v)
% DISPLAY Display a variable, limiting the number of elements shown.
name = inputname(1);
if isempty(name)
name = 'ans';
end
maxElementsShown = 500;
newlines = repmat('\n',1,~strcmp(get(0,'FormatSpacing'),'compact'));
if numel(v)>maxElementsShown,
warning('display:varTooLong','Data not displayed because of length.');
% OR show the first N=maxElementsShown elements
% builtin('disp', v(1:maxElementsShown));
elseif numel(v)>0,
fprintf([newlines '%s = \n' newlines], name);
builtin('disp', v);
end
end
For example,
>> xx=1:10
xx =
1 2 3 4 5 6 7 8 9 10
>> xx=1:1e4
Warning: Data not displayed because of length.
> In double.display at 17
EDIT: Updated to respect 'compact' and 'loose' output format preference.
EDIT 2: Prevent displaying an empty array. This makes whos and other commands avoid an unnecessary display.

Puzzling "Subscripted assignment dimension mismatch" only during loop using portopt & ewstats

I am tearing my hair out over this one.
I have a set of daily returns of 4 assets, using a 10 day window I loop over the whole dataset (from i = 1 to 50) performing a number of calculations and building optimal portfolios. This involves using portopt.
[PortRisk(:,i), PortReturn(:,i), PortWts(:,:,i)] = portopt(ExpReturn(i,:), ExpCovariance(:,:,i), [], [], ConSet);
The inputs, ExpReturn and ExpCovariance are generated using ewstats
[ExpReturn(i,:), ExpCovariance(:,:,i)] = ewstats(RetSeries, 0.94)
Now, on the final 50th iteration (and only the 50th - all previous work fine), I get the following error:
??? Subscripted assignment dimension mismatch. Error in ==> Script at 10
[PortRisk(:,i), PortReturn(:,i), PortWts(:,:,i)] = portopt(ExpReturn(i,:), ExpCovariance(:,:,i), [], [], ConSet);
Note, I see no issue with RetSeries as ExpReturn and ExpCovariance generated by ewstats are size <50x4> and <4x4x50> respectively.
I have tried everything i can think of to hunt down the error, including checking size(), using breakpoints, preallocating the matrices etc etc. Oddly, if i remove the loop, set i = 50, it works. Furthermore, if instead of ewstats I simply use mean() and cov() - they work on the 50th iteration. If i replace one, ExpReturn for example, with a mean(RetSeries), it works. Similarly, replacing ExpCovariance with cov(RetSeries) - works. But both ExpReturn and ExpCovariance together always fail.
What is causing the error?
EDIT:
Using dbstop if error, I can see:
PortRisk <10x50>
PortReturn <10x50>
PortWts<10x4x49>
ExpReturn <50x4>
ExpCovariance<4x4x50>
so the problem is PortWts but I do not understand why now it is not the right dimensions when it was for 49 other iterations. Also, the offending error line is the first point in the loop PortWts is mentioned, so nothing is messing with it beforehand
Try setting dbstop if error, and run your code again. MATLAB will enter debug mode at the exact point where the error occurs.
Here is a screencast by Doug Hull showing how
EDIT
Change the offending line to:
[a,b,c] = portopt(ExpReturn(i,:), ExpCovariance(:,:,i), [], [], ConSet);
then assign each individually:
PortRisk(:,i) a;
PortReturn(:,i) = b;
PortWts(:,:,i) = c;
Now when it fails, it will show you exactly which output did not have the expected size. Combined with the above trick, you can now inspect the variables in your workspace at the time of the error, and figure out what is wrong..
EDIT2
In addition, add the following test in between the two (before assigning):
if isempty(a) || isempty(b) || isempty(c)
keyboard %# enter debug mode. Or issue an error
end