Corner Cases, Unexpected and Unusual MATLAB [closed] - matlab

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
Over the years, reading others code, I encountered and collected some examples of MATLAB syntax which can be at first unusual and counterintuitive. Please, feel free to comment or complement this list. I verified it with r2006a.
MATLAB always returns first output argument of a function (if it has at least one) into its caller workspace, also unexpectedly if function is being called without returning arguments like myFunc1(); myFunc2(); the caller workspace still would contain first output of myFunc2(); as "invisible" ans variable. It could play an important role if ans is a reference object - it would remain alive.
set([], 'Background:Color','red')
MATLAB is very forgiving sometimes. In this case, setting properties to an array of objects works also with nonsense properties, at least when the array is empty. Such arrays usually come from harray = findobj(0,'Tag','NotExistingTag')
myArray([1,round(end/2)])
This use of end keyword may seem unclean but is sometimes very handy instead of using length(myArray).
any([]) ~= all([])
Surprisigly any([]) returns false and all([]) returns true. And I always thought that all is stronger then any.
EDIT:
with not empty argument all() returns true for a subset of values for which any() returns true (e.g. truth table). This means that any() false implies all() false. This simple rule is being violated by MATLAB with [] as argument.
Loren also blogged about it.
Select(Range(ExcelComObj))
Procedural style COM object method dispatch. Do not wonder that exist('Select') returns zero!
[myString, myCell]
MATLAB makes in this case an implicit cast of string variable myString to cell type {myString}. It works, also if I would not expect it to do so.
[double(1.8), uint8(123)] => 2 123
Another cast example. Everybody would probably expect uint8 value being cast to double but Mathworks have another opinion. Without a warning this behavior is very dangerous.
a = 5;
b = a();
It looks silly but you can call a variable with round brackets. Actually it makes sense because this way you can execute a function given its handle.
Syntax Foo(:) works not only on data but also with functions if called as Bar.Foo(:), in this scenario the function input argument is passed as char colon ':'.
For example let Bar.Foo = #(x) disp(x)
Now calling Bar.Foo(:) prints char ':' in the MATLAB Command Window.
This strange feature works with all MATLAB 7 versions without warnings.
a = {'aa', 'bb'
'cc', 'dd'};
Surprsisingly this code neither returns a vector nor rises an error but defins matrix, using just code layout. It is probably a relict from ancient times.
EDIT: very handy feature, see the comment by gnovice.
set(hobj, {'BackgroundColor','ForegroundColor'},{'red','blue'})
This code does what you probably expect it to do. That function set accepts a struct as its second argument is a known fact and makes sense, and this sintax is just a cell2struct away.
Equvalence rules are sometimes unexpected at first. For example 'A'==65 returns true (although for C-experts it is self-evident). Similarly isequal([],{}) retuns, as expected, false and isequal([],'') returns true.
The string-numeric equivalence means that all string functions can be used also for numeric arrays, for example to find indices of a sub-array in a large array:
ind = strfind( [1 2 3 4 1 2 3 4 1 2 3 4 ], [2 3] )
MATLAB function isnumeric() returns false for booleans. This feels just ... false :-)
About which further unexpected/unusual MATLAB features are you aware?

Image coordinates vs plot coordinates Used to get me every time.
%# create an image with one white pixel
img = zeros(100);
img(25,65) = 1;
%# show the image
figure
imshow(img);
%# now circle the pixel. To be sure of the coordinate, let's run find
[x,y] = find(img);
hold on
%# plot a red circle...
plot(x,y,'or')
%# ... and it's not in the right place
%# plot a green circle with x,y switched, and it works
plot(y,x,'og')
Edit 1
Array dimensions
Variables have at least two dimensions. Scalars are size [1,1], vectors are size [1,n] or [n,1]. Thus, ndims returns 2 for any of them (in fact, ndims([]) is 2 as well, since size([]) is [0,0]). This makes it a bit cumbersome to test for the dimensionality of your input. To check for 1D arrays, you have to use isvector, 0D arrays need isscalar.
Edit 2
Array assignments
Normally, Matlab is strict with array assignments. For example
m = magic(3);
m(1:2,1:3) = zeros(3,2);
throws a
??? Subscripted assignment dimension mismatch.
However, these work:
m(1:2,1:2) = 1; %# scalar to vector
m(2,:) = ones(3,1); %# vector n-by-1 to vector 1-by-n (for newer Matlab versions)
m(:) = 1:9; %# vector to 'linearized array'
Edit 3
Logical indexing with wrongly sized arrays Good luck debugging this!
Logical indexing seems to make a call to find, since your logical array doesn't need the same amount of elements as there are indices!
>> m = magic(4); %# a 4-by-4 array
>> id = logical([1 1 0 1 0])
id =
1 1 0 1 0
>> m(id,:) %# id has five elements, m only four rows
ans =
16 2 3 13
5 11 10 8
4 14 15 1
%# this wouldn't work if the last element of id was 1, btw
>> id = logical([1 1 0])
id =
1 1 0
>> m(id,:) %# id has three elements, m has four rows
ans =
16 2 3 13
5 11 10 8

Instead of listing examples of weird MATLAB syntax, I'll address some of the examples in the question that I think make sense or are expected/documented/desired behavior.
How ANY and ALL handle empty arguments:
The result of any([]) makes sense: there are no non-zero elements in the input vector (since it's empty), so it returns false.
The result of all([]) can be better understood by thinking about how you might implement your own version of this function:
function allAreTrue = my_all(inArray)
allAreTrue = true;
N = numel(inArray);
index = 1;
while allAreTrue && (index <= N)
allAreTrue = (inArray(index) ~= 0);
index = index + 1;
end
end
This function loops over the elements of inArray until it encounters one that is zero. If inArray is empty, the loop is never entered and the default value of allAreTrue is returned.
Concatenating unlike classes:
When concatenating different types into one array, MATLAB follows a preset precedence of classes and converts values accordingly. The general precedence order (from highest to lowest) is: char, integer (of any sign or number of bits), single, double, and logical. This is why [double(1.8), uint8(123)] gives you a result of type uint8. When combining unlike integer types (uint8, int32, etc.), the left-most matrix element determines the type of the result.
Multiple lines without using the line continuation operator (...):
When constructing a matrix with multiple rows, you can simply hit return after entering one row and enter the next row on the next line, without having to use a semicolon to define a new row or ... to continue the line. The following declarations are therefore equivalent:
a = {'aa', 'bb'
'cc', 'dd'};
a = {'aa', 'bb'; ...
'cc', 'dd'};
a = {'aa', 'bb'; 'cc', 'dd'};
Why would you want MATLAB to behave like this? One reason I've noticed is that it makes it easy to cut and paste data from, for example, an Excel document into a variable in the MATLAB command window. Try the following:
Select a region in an Excel file and copy it.
Type a = [ into MATLAB without hitting return.
Right-click on the MATLAB command window and select "Paste".
Type ]; and hit return. Now you have a variable a that contains the data from the rows and columns you selected in the Excel file, and which maintains the "shape" of the data.

Arrays vs. cells
Let's look at some basic syntax to start with. To create an array with elements a, b, c you write [a b c]. To create a cell with arrays A, B, C you write {A B C}. So far so good.
Accessing array elements is done like this: arr(i). For Cells, it's cell{i}. Still good.
Now let's try to delete an element. For arrays: arr(i) = []. Extrapolating from examples above, you might try cell{i} = {} for cells, but this is a syntax error. The correct syntax to delete an element of a cell is, in fact, the very same syntax you use for arrays: cell(i) = [].
So, most of the time you access cells using special syntax, but when deleting items you use the array syntax.
If you dig deeper you'll find that actually a cell is an array where each value is of a certain type. So you can still write cell(i), you'll just get {A} (a one-valued cell!) back. cell{i} is a shorthand to retrieve A directly.
All this is not very pretty IMO.

Related

Can you explain what this line does in Matlab

I'm new to Matlab and I'm just stuck with this line of code:
[r,c] = find(abs(fh) <= 2 );
Beware: ironically it was easy for me understanding what the right part of the assignment is.
The left part however (which is maybe the definition of a variable)... I don't know how to search because I have too generic results by googling just square brackets with something inside.
My assumption is this line of code is creating some a matrix with r rows and c columns but r and c are nowhere to be found in the rest of the code.... or maybe it's a simple array with two elements... but it doesn't make much sense to me honestly.
Can you guys help me please?
Whenever you see that syntax, it means that the function being called is returning more than one output argument (two in this case).
The best way to learn about the function output arguments is to check the documentation:
https://www.mathworks.com/help/matlab/ref/find.html#d120e368337
[row,col] = find(___) returns the row and column subscripts of each
nonzero element in array X using any of the input arguments in
previous syntaxes.
The output arguments are positional, so r is row, c is col.
Take a look in Matlab find() docs.
If X is a vector, then find returns a vector with the same orientation as X.
If X is a multidimensional array, then find returns a column vector of the linear indices of the result.
If X contains no nonzero elements or is empty, then find returns an empty array.
If you call
X = [18 3 1 11;
8 10 11 3;
9 14 6 1;
4 3 15 21 ]
[row,col] = find(X>0 & X<10,3)
You will get:
row = 3×1
2
3
4
col = 3×1
1
1
1
Which represents the index (row number and column number) of each elements that satifies the condition you defined. Since it returns more than 1 value, you can divide the output in two different variables and that is what the left side represents.

Printing progress in command window

I'd like to use fprintf to show code execution progress in the command window.
I've got a N x 1 array of structures, let's call it myStructure. Each element has the fields name and data. I'd like to print the name side by side with the number of data points, like such:
name1 number1
name2 number2
name3 number3
name4 number4
...
I can use repmat N times along with fprintf. The problem with that is that all the numbers have to come in between the names in a cell array C.
fprintf(repmat('%s\t%d',N,1),C{:})
I can use cellfun to get the names and number of datapoints.
names = {myStucture.name};
numpoints = cellfun(#numel,{myStructure.data});
However I'm not sure how to get this into a cell array with alternating elements for C to make the fprintf work.
Is there a way to do this? Is there a better way to get fprintf to behave as I desire?
You're very close. What I would do is change your cellfun call so that the output is a cell array instead of a numeric array. Use the 'UniformOutput' flag and set this to 0 or false.
When you're done, make a new cell array where both the name cell array and the size cell array are stacked on top of each other. You can then call fprintf once.
% Save the names in a cell array
A = {myStructure.name};
% Save the sizes in another cell array
B = cellfun(#numel, {myStructure.data}, 'UniformOutput', 0);
% Create a master cell array where the first row are the names
% and the second row are the sizes
out = [A; B];
% Print out the elements side-by-side
fprintf('%s\t%d\n', out{:});
The trick with the third line of code is that when you unroll the cell array using {:}, this creates a comma-separated list unrolled in column-major format, and so doing out{:} actually gives you:
A{1}, B{1}, A{2}, B{2}, ..., A{n}, B{n}
... which provides the interleaving you need. Therefore, providing this order into fprintf coincides with the format specifiers that are specified and thus gives you what you need. That's why it's important to stack the cell arrays so that each column gives the information you need.
Minor Note
Of course one should never forget that one of the easiest ways to tackle your problem is to just use a simple for loop. Even though for loops are considered bad practice, their performance has come a long way throughout MATLAB's evolution.
Simply put, just do this:
for ii = 1 : numel(myStructure)
fprintf('%s\t%d\n', myStructure(ii).name, numel(myStructure(ii).data));
end
The above code is arguably more readable in comparison to what we did above with cell arrays. You're accessing the structure directly rather than having to create intermediate variables for the purpose of calling fprintf once.
Example Run
Here's an example of this running. Using the data shown below:
clear myStructure;
myStructure(1).name = 'hello';
myStructure(1).data = rand(5,1);
myStructure(2).name = 'hi';
myStructure(2).data = zeros(3,3);
myStructure(3).name = 'huh';
myStructure(3).data = ones(6,4);
I get the following output after running the printing code:
hello 5
hi 9
huh 24
We can see that the sizes are correct as the first element in the structure is simply a random 5 element vector, the second element is a 3 x 3 = 9 zeroes matrix while the last element is a 6 x 4 = 24 ones matrix.

Logical indexing: What is going on here?

I have read this documentation on logical indexing, but it doesn't clarify my problem.
I have this line of code:
y = rand(20,3);
aa= unidrnd(2,20,3) - 1;
val = ( aa & y<1.366e-04) | (~aa & y<8.298e-04);
aa(val) = ~aa(val);
I cannot understand what is going on in the last line aa(val) = ~aa(val);.
A similar question was asked here but it does not answer the question to the logical indexing specifically or what the logical values were implying.
when the code is run, val's elements are zeroes.
Here's the tricky part, if I run only aa(val) or ~aa(val) I get Empty matrix: 0-by-1. But if I run the entire line aa(val) = ~aa(val);, i get a matrix aa(with 0's and 1's, 20x3).
'~' is performing the inversion of the values right? That means it should be assigning a matrix of 1's (20x3). But apparently it is not!!I
Can someone please breakdown to me what is happening in the last line.
If all of val's elements are zeros (actually logical falses or you would get an error), then indexing aa by val would return nothing (as you point out). So when you do the whole line
aa(val) = ~aa(val)
it is essentially assigning the inverse of nothing to nothing and hence it doesn't do anything and should return aa unchanged. Remember that the ~ is being applied to aa(val) and NOT to val itself so it inverts the empty matrix aa(val) and then assigns this to the empty matrix aa(val).

Please help me with line 8 of the code below?

Some one gave me this code to implement but I am not able to understand what Line 8 does in the code below. What does this mean y(y
clear;
lambda=0.1;
T=100;
M=50;
for i=1:M
x=exprnd(1/lambda,1,2*lambda*T);
y=cumsum(x);
pp{i}=y(y<T);
end
If line 8 is pp{i} = y(y < T), then it's creating a "cell array" (so now you can google it) with the {} syntax and setting element i to all the values in y that are less than T (i.e. 100)`. That is:
y<T
is an array the size of y with 1 in the places where the corresponding element of y is less than T.
y(y<T)
is then selecting only those elements. So it is probably smaller than y, and all the entries are less than T.
And then:
pp{i} = y(y<T)
is assigning that array to element i of a "cell array". Cell arrays are like normal arrays except that each element can be a different type or a different size.
it means, retrieve all items of vector y where y[i] < T
see also the find method

Combination of colon-operations in MATLAB

I have a question concerning the colon operator and expansion of vectors in MATLAB. My problem is to understand how the following line of code expands, to be able to use it for other sequences. The line of MATLAB code is:
a(1:2:5) = 1:-4:-7
Note that a is not defined before the expansion. This returns the vector
a = 1 0 3 0 -7
I know how the colon operator works with {start}:{step}:{stop}, my problem is to understand how and why the combination of a(1:2:5)and 1:-4:-7 returns a vector of five elements with zeros in position 2 and 5?
Whenever Matlab detects you're indecing to an element outside the current bounds of the matrix/array, it will automatically pad the missing elements with zeros:
>> clear b; b(10) = 5
b =
0 0 0 0 0 0 0 0 0 5
This feature is both very useful, and very dangerous. It is useful for the fact declarations can be made very easy, such as your own case. You can create a whole array of custom-made classes by issuing something like
myClassArray(500) = myClass(1, 2);
which is infinitely better than something like
% cannot pre-allocate (zeros() or ones() give double/uint8/..., not myClass)
for ii = 1:499
myClassArray(ii) = myClass; % so, growing array
end
myClassArray(500) = myClass(1,2);
But, growing arrays can be hard to spot:
a = zeros(10,1);
for ii = 1:10
a(ii+1) = rand;
end
which can make performance drop tremendously. Also, when you translate code prototyped in Matlab to a statically-typed language like C++, copying this code will result in buffer overflows and thus segfaults.
Now, going back to your case:
clear a; a(1:2:5) = 1:-4:-7
The 1:2:5 will expand to the array [1 3 5], and the 1:-4:-7 will give the values [1 -3 -7]. Since the variable a does not exist yet, Matlab will create a new one and fill the elements [1 3 5] with the values [1 -3 -7]. The indices that have been skipped in order to initialize variable a (namely, [2 4]) will then have been initialized automatically to zero.
If you're familiar with Python, it's a bit like the syntax to assign multiple values to multiple variables
x,y = 1,2
But in your Matlab case, these different variables are indices to a non-existent array, which requires "filling the holes with something" to make it a valid, consistent array.
Does this make things clear?
when you define a(1:2:5), it creates a size 5 vector (zero-valued), and selecting odd indexed(3 of them exists) cells. 1:-4:-7 creates three values (not five). Finally your selected three cells are filled with data of 3 values coming from 1:-4:-7