3
votes

I am trying to compute the gradient of a 3-D matrix using MATLAB (version 2016a). If I type "help gradient" it says the following:

"HX and HY can either be scalars to specify the spacing between coordinates or vectors to specify the coordinates of the points. If HX and HY are vectors, their length must match the corresponding dimension of F." (emphasis mine).

Here is a sample code:

x = 1:30; nx = length(x);
y = 1:62; ny = length(y);
z = 1:23; nz = length(z);

F = rand(nx,ny,nz);

[FX,FY,FZ] = gradient(F,x,y,z);

Here, I am inputting vectors x, y, and z to compute the gradient. These are vectors and it says in the help that HX and HY must have a length matching the corresponding dimension of F. The x-dimension of F has length nx. So the x vector also has length nx. It should work, according to the help.

However, I get an error:

Index exceeds matrix dimensions.

Error in gradient (line 112)
            h = h(3:n) - h(1:n-2);

When I dig a little deeper into the "gradient" function I come across this line in the "parse_inputs" embedded function:

% Swap 1 and 2 since x is the second dimension and y is the first.
loc = v;
if ndim > 1
    loc(2:-1:1) = loc(1:2);
end

What is going on here?

Why does MATLAB swap the x and y dimensions?

If I do the following code and swap the x and y vectors, then the code works.

x = 1:30; nx = length(x);
y = 1:62; ny = length(y);
z = 1:23; nz = length(z);

F = rand(nx,ny,nz);

[FX,FY,FZ] = gradient(F,y,x,z);

I just don't understand why. I've looked around on stack overflow but can't find any answer to the question.

In any case, it seems that the help is somewhat misleading because you actually need to swap x and y to make the function work...

1
Closely related to issues with meshgrid, as discussed here and here. - gnovice

1 Answers

3
votes

It is not gradient that swaps dimensions, it's everything else...

MATLAB indexes arrays as (row,column), and array sizes are given in the same order, as [height,width].

However, whenever the documentation to any function mentions x and y, the x is always horizontal and y vertical. So in a way MATLAB indexes as (y,x).

The right way to fix your code is:

x = 1:30; nx = length(x);
y = 1:62; ny = length(y);
z = 1:23; nz = length(z);

F = rand(ny,nx,nz);   % <<< Note the order here!

[FX,FY,FZ] = gradient(F,x,y,z);

Personal opinion: This is terribly confusing, I have seen lots of people making mistakes because of this, and have made quite a few mistakes myself as well. But they are very consistent with this in the MATLAB documentation, using (i,j) or (x,y) depending on the required order -- with the exception of ndgrid, where the documentation uses x1,x2,x3,... but should really have used a different letter.