Assigning empty matrix to empty sub-matrix in Matlab - matlab

When running following code in Matlab:
a = magic(3);
b = [];
a([],:) = [] % works
a([],:) = b % doesn't work
I get an error when using variable 'b':
>> tmp
a =
8 1 6
3 5 7
4 9 2
Subscripted assignment dimension mismatch.
Error in tmp (line 5)
a([],:) = b
Does anyone know what's going on here? Why one assignment works and the other doesn't?

Here's my guess at why Matlab behaves like that:
I think that assigning to [] can be considered a special operator, i.e. a(1,:) = [] will essentially delete the first row of a. So even though size(a(1,:)) differs from size([]), I reckon the Matlab interpreter knows that this special case is not an assignment.
However a(1,:) = b when b=[] will give you a subscript dimension mismatch. I think this is correct behaviour because in this case you are assigning, and you're trying to assign a 0-by-0 to a 1-by-3 which is a dimension mismatch. The same goes for a([],:) = b, you're trying to fit a 0-by-0 into a 0-by-3 space which is again a mismatch.
So in conclusion, the second case is an assignment operator and so the error makes sense. The first case is a special delete operator and hence no error.
I have no references for any of this (this is all I could find in the docs but it doesn't really cover everything)
However I don't think this explains all the behaviour, some examples brought up from the comments:
Assume:
a = magic(3);
a2 = magic(4);
b = [];
a([],:) + a2([],:) gives a dimension mismatch error as expected.
a([],:) = a2([],:) does not throw an error... which to me is not expected
a([],:) = b(:) also does NOT throw an error... which is again quite strange, unless we can assume that the (:) operation returns a comma separated list like the {:} does (although I know that is not the case)???
These cases seem inconsistent to me.
We can expand on case 2:
a([],:) = zeros(0,0)
a([],:) = zeros(0,2)
a([],:) = zeros(0,3)
a([],:) = zeros(0,4)
only he first case throws an error and the other 3 are accepted by Matlab. Looks like this answer is just creating further questions :/

Related

Trying to develop closed form solutions of second order DE

Basically, I have this function in matlab:
function yy = homo2nd(tt,polycc,y0,v0)
rr = roots(polycc);
cc = [1 1; rr(1) rr(2)\[y0; v0]];
yy = cc(1)*exp(rr(1)*tt) + cc(2) * exp(rr(2)*tt);
yy = round(yy,8);
end
I understand that roots takes the roots of an array signifying the coefficients of the left side of the equation. I feed roots and argument like [1 1 1] and it spits out the eigenvalues of that function.
From there I am lost.
I define tt in the command shell like this:
tt = linspace(0,2*pi,100).
I call homo2nd and feed it arguments (tt,[1 1 1], 1, 1)
When I try to feed roots the argument [1 1 1] like I said I get this error:
Error using horzcat
Dimensions of arrays being concatenated are not consistent.
I just need help interpreting the code. Why are the arrays horizontally mismatched?
The error is occuring on this line
cc = [1 1; rr(1) rr(2)\[y0; v0]];
So let's look at this, the 1 1 is fine, it's saying there's a row vector [1,1].
The next part is where the error occurs, the ; moves us to a second row. The first element of that row is rr(1), this is fine.
However, the second element rr(2)\[y0; v0] is using the mldivide command and the result of this isn't a single element, hence the error.

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).

MATLAB Incorrect number of right hand side elements

Matlab's syntax is infuriating, specifically with structs. In the Bioinformatics toolkit, there is a method called jcampread(File) which is described here.
In the description, the method jcampread() takes a Filepath and outputs into a struct called jcampStruct. From my understanding, in Matlab, you don't declare return variable types like you do in C: you just give the return variable a name and it somehow knows that the return of jcampread() method will be a jcampStruct. How it does, I have no idea, but it does.
I put in the code exactly how their example shows in step 4 of the Example section, and I get the following error message back from Matlab:
Incorrect number of right hand side elements in
dot name assignment. Missing [] around left hand
side is a likely cause.
Error in jcampread>ntupleRead (line 510)
dataBlock.ZName = name{Zidx};
Error in jcampread (line 192)
dataBlocks = ntupleRead(fid);
This site says the problem occurs "when f has more than one matrix element." Code is below:
»f.a = [1 0]
f =
a: [1 0]
»f.b = [1 2]
f =
a: [1 0]
b: [1 2]
»f = setfield(f,'a',[2 2])
f =
a: [2 2]
b: [1 2]
»f(2).a=1
f =
1x2 struct array with fields:
a
b
»f = setfield(f,'a',[2 2])
??? Error using ==> setfield
Incorrect number of right hand side elements in dot name assignment.
Missing [] around left hand side is a likely cause.
I assume this means the matrix f looks like this:
f = [ [a1; b1]; [a2; b2]; ]
f = [ [[2 2]; [1 2]]; [[1]; []]; ]
When they tried to update f.a which was set to
f.a = [[2 2]; [1]]
...to a single element [2 2], it doesn't like that because f.a is currently a matrix with 2 vector elements. Basically if you are going to reassign f.a (all elements of the attribute a of matrix f), you have to reassign f.a to have the same number of elements as it currently has.
I think that is why this error is occuring in the setfield example.
My question: how does this apply to jcampread()? jcampStruct is literally a structure with the same attributes, and those attributes are assigned only once. I do not understand:
a. How matlab knows the return value of jcampread() is a jcampStruct, and
b. Why (given that it knows (a)), the 'Incorrect number of right hand..' error message is firing here.
Can anyone clear this up for me?
You are creating a non scalar structure and there is no way to assign at once, i.e. without a loop, a different value to the same field of each sub-structure.What does it mean?
Scalar structure
s.a = 1;
size(s)
ans =
1 1
Now, adding fields doesn't change the size of the structure:
s.b = 2;
size(s)
ans =
1 1
Non-scalar structure
However, assigning a value to the same field, but into a position > 1 of the structure, will grow it a non-scalar one:
s(2).a = 3
size(s)
ans =
1 2
Also, notice how the sub-structure in position 2 replicates/pre-allocates the fields of the initial structure even though you assigned to a alone:
s(2)
ans =
a: 3
b: []
Pointers
Additionally, the field s(2).b is just an empty pointer:
whos s
Name Size Bytes Class
s 1x2 496 struct
and by adding a scalar double (8 bytes), we get
s(2).b = 4;
whos s
Name Size Bytes Class
s 1x2 608 struct
Pro of non-scalar structure
What you can do with a non-scalar structure, is retrieve one field across all sub-structure (considering you don't run into concatenation issues):
for ii = 1:100
s(ii).a = rand(1,2);
end
cat(1,s.a)
the last command will concatenate all values of a single field from all sub-structure into a 100 by 2 array.
Cons
To assign different values across the sub-structures, even if the same field, you need to loop (as above in the for loop).
At most you could deal() the same values into one field across all sub-structures:
clear s
[s(1:100)] = deal([1, 2]);

matlab reshape function - error on number of elements

Hi I have the following code
A = squeeze(hourly_surplus(1,1,1,:));
B = reshape(A,365,24);
Where size(A) = 8760 x 1
however I get the error
Error using reshape
To RESHAPE the number of elements must not change
This error appears on the line of "B", however I think that A has 8760 elements and B = 365 x 24 which also is 8760. What could be going wrong?
Thanks
This:
A=rand(8760,1);
B=reshape(A,365,24);
works fine, so the problem is with your A.

Corner Cases, Unexpected and Unusual MATLAB [closed]

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.