Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Corner Cases, Unexpected and Unusual MATLAB [closed]

Tags:

matlab

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.