separate 3D matrix like numpy - matlab

I am converting numpy code to matlab. tensor is a 3D matrix of 6 x 2D matrices of the tensor components. This code appears to then split them back into those 6 separate 2D matrices.
gxx, gxy, gxz, gyy, gyz, gzz = tensor
Can I do this as eloquently in matlab?
re OmG: gxx, etc are the six tensor components of a gravity grid. xx for 2nd derivative of x in the x direction, xy is the 2nd derivative of x in the y direction, etc. Those components will be put through a simple equation to calculate the invariants which will then calculate the depth of the gravity anomaly.

As #Div-iL says, you could simply assign each variable to a slice of the 3D array:
tensor = rand(5,3,6); % Random data to play with
gxx = tensor(:,:,1);
gxy = tensor(:,:,2);
% etc
However if you really wanted to do it automatically you could generate a cell-array of 2D arrays (using mat2cell) and then assign them to variables using a comma-separated list assignment:
[nx,ny,nz] = size(tensor);
ca = mat2cell(tensor, nx, ny, ones(1,nz));
[gxx, gxy, gxz, gyy, gyz, gzz] = ca{:};
However, that all feels a bit hairy to me. If you're looking for a natively-supported one-liner (like your example) then I think you're out of luck.

Related

plot diagonal slices of a 3D matrix with imagesc()

I'm new to Matlab and I really need help with the following problem:
I have a 255 x 255 x 255 matrix and I would like to plot its 2D slices with imagesc().
I understand that for plotting slices parallel to the x, y, z planes I could just specify the slice with something like matrix(:,:,i), but how would I do that if I want to plot the x = y slice, or in general any x = n*y slice?
What I'm thinking is to interpolate the matrix to those planes and then extract the slice, but I'm a little stuck on how.
Specifically for the x = y slice I've been trying to build a 2D matrix by using the diag() command for each z slice and by setting the new_matrix = matrix(i,i,:) for i=1:255, but that didn't seem to be working.
for that Matlab gave you slice !
[X,Y,Z] = meshgrid(-5:0.2:5);
V = X.*exp(-X.^2-Y.^2-Z.^2);
[xsurf,ysurf] = meshgrid(-2:0.2:2);
zsurf = xsurf/2+ysurf/2;
slice(X,Y,Z,V,xsurf,ysurf,zsurf)
and you can play with the camera view angle to emulate the imagesc feel, fir example try view(0, 90) after the code I wrote...
By the way... if you insists on doing the cut and using imagesc the way you wanted, this is how with the example I gave:
for n=1:size(X,1)
D(:,n)=squeeze(V(n,n,:));
end
imagesc(D)

Convert an Array from Spherical to Cartesian Coordinates in MATLAB

I am working in MATLAB with a formula which indexes points on a unit sphere in spherical coordinates.
[i, j] = ndgrid(1:N_theta, 1:N_phi);
theta = (i-1)*2*pi/N_theta;
phi = (j)*pi/(N_phi+1);
r = 1;
b = [theta(:).'; phi(:).'; r * ones(1,numel(theta))];
Let's assume I choose particular values for N_theta and N_phi and that each point has a position vector in spherical coordinates, where the first component is theta, the second component is phi and the third component is r. Running the formula then creates an array (I've called it b) which takes the position vector for each of the N points and slots them all next to each other to make a 3xN matrix.
I essentially just need to take that array and convert it so it's the same array with the vectors all next to each other but now the position vectors are in Cartesian coordinates (we could call the new array B).
I have looked up the sph2cart function in MATLAB which is designed for that purpose but I'm not sure if I am using it correctly and am hoping someone could point it what I am doing wrong. I have tried this, for example
B=sph2cart(b(1,:),b(2,:),b(3,:));
and
B = sph2cart(theta,phi,r);
but they both create matrices which are too small, so something is obviously going wrong.

Matlab- Given matrix X with xi samples, y binary column vector, and a vector w plot all these into 3d graph

I have started to learn Machine Learning, and programming in matlab.
I want to plot a matrix sized m*d where d=3 and m are the number of points.
with y binary vector I'd like to color each point with blue/red.
and plot a plane which is described with the vertical vector to it w.
The problem I trying to solve is to give some kind of visual representation of the data and the linear predictor.
All I know is how to single points with plot3, but no any number of points.
Thanks.
Plot the points using scatter3()
scatter3(X(y,1),X(y,2),X(y,3),'filled','fillcolor','red');
hold on;
scatter3(X(~y,1),X(~y,2),X(~y,3),'filled','fillcolor','blue');
or using plot3()
plot(X(y,1),X(y,2),X(y,3),' o','MarkerEdgeColor','red','MarkerFaceColor','red');
hold on;
plot(X(~y,1),X(~y,2),X(~y,3),' o','MarkerEdgeColor','blue','MarkerFaceColor','blue');
There are a few ways to plot a plane. As long as w(3) isn't very close to 0 then the following will work okay. I'm assuming your plane is defined by x'*w+b=0 where b is a scalar and w and x are column vectors.
x1min = min(X(:,1)); x2min = min(X(:,2));
x1max = max(X(:,1)); x2max = max(X(:,2));
[x1,x2] = meshgrid(linspace(x1min,x1max,20), linspace(x2min, x2max, 20));
x3 = -(w(1)*x1 + w(2)*x2 + b)/w(3);
surf(x1,x2,x3,'FaceColor',[0.6,0.6,0.6],'FaceAlpha',0.7,'EdgeColor',[0.4,0.4,0.4],'EdgeAlpha',0.4);
xlabel('x_1'); ylabel('x_2'); zlabel('x_3'); axis('vis3d');
Resulting plot

2D convolution of slices of 3D matrix

I'm trying to do a bunch of rolling sums over matrices in MATLAB. In order to avoid loops I've used repmat to layer my 2D matrices into a 3D structure. However, now the fast convolution function conv2 can no longer be used for the accumulator. However, the N-dimensional convolution function (convn) is not what I'm looking for either as it literally convolves all 3 dimensions. I want something that will do a 2D convolution on each slice and return a 3D matrix.
Tiling the matrices in 2D instead of layering them in 3D won't work because it will corrupt the convolution edge cases. I could pad with zeros in between but then it starts getting kind of messy.
In other words, without a for-loop, how can I perform the following:
A = ones(5,5,5);
B = zeros(size(A));
for i = 1 : size(A, 3)
B(:,:,i) = conv2(A(:,:,i), ones(2), 'same');
end
Thanks in advance for the help!
convn will work with an n-dimensional matrix and a 2-dimensional filter. Simply:
A = ones(5,5,5);
B = convn(A, ones(2), 'same');
You can use some padding with zeros and reshaping like so -
%// Store size parameters
[m,n,r] = size(A)
[m1,n1] = size(kernel)
%// Create a zeros padded version of the input array. We need to pad zeros at the end
%// rows and columns to replicate the convolutionoperation around those boundaries
Ap = zeros(m+m1-1,n+n1-1,r);
Ap(1:m,1:n,:) = A;
%// Reshape the padded version into a 3D array and apply conv2 on it and
%// reshape back to the original 3D array size
B_vect = reshape(conv2(reshape(Ap,size(Ap,1),[]),kernel,'same'),size(Ap))
%// Get rid of the padded rows and columns for the final output
B_vect = B_vect(1:m,1:n,:);
The basic idea is to reshape the input 3D array into a 2D array and then apply the 2D convolution on it. Extra step is needed with padding so as to have the same behavior as you would see with conv2 around the boundaries.

How to plot a 3-column matrix as a color map in MATLAB?

I have a matrix containing the temperature value for a set of GPS coordinates. So my matrix looks like this :
Longitude Latitude Value
--------- -------- -----
12.345678 23.456789 25
12.345679 23.456790 26
%should be :
% x y z
etc.
I want to convert this matrix into a human-viewable plot like a color plot (2D or 3D), how can I do this?
3D can be something like this :
or just the 2-D version of this (looking from top z-axis).
What Have I Tried
I know MATLAB has surf and mesh functions but I cannot figure out how to use them.
If I call
surf(matrix(:,1) , matrix(:,2) , matrix(:,3));
I get the error :
Error using surf (line 75)
Z must be a matrix, not a scalar or vector
Thanks in advance for any help !
P.S : It would also be great if there is a function that "fills" the gaps by interpolation (smoothing, whatever :) ). Since I have discrete data, it would be more beautiful to represent it as a continous function.
P.S 2 : I also want to use plot_google_map in the z=0 plane.
A surprisingly hard-to-find answer. But I'm lucky that somebody else has asked almost the same question here.
I'm posting the answer that worked for me :
x = matrix(:,1);
y = matrix(:,2);
z = matrix(:,3);
xi=linspace(min(x),max(x),30)
yi=linspace(min(y),max(y),30)
[XI YI]=meshgrid(xi,yi);
ZI = griddata(x,y,z,XI,YI);
contourf(XI,YI,ZI)
which prints a nice color map.
One option that avoids unnecessarily gridding your data would be to compute the Delaunay triangulation of the scattered data points and then using a command like trisurf to plot the data. Here's an example:
N=50;
x = 2*pi*rand(N,1);
y = 2*pi*rand(N,1);
z = sin(x).*sin(y);
matrix = [x y z];
tri = delaunay(matrix(:,1),matrix(:,2));
trisurf(tri,matrix(:,1),matrix(:,2),matrix(:,3))
shading interp
Suppose your matrix is nx3. Then you can create the grid as follows:
xMin=min(myMat(:,1));
xMax=max(myMat(:,1));
yMin=min(myMat(:,2));
yMax=max(myMat(:,2));
step_x=0.5; %depends on your data
[xGrid,yGrid]=meshgrid(xMin:step_x:xMax,yMin:step_y:yMax);
Now, put your data in the third column to the appropriate indices, in the new matrix say, valMat.
You can use surf now as follows:
surf(xGrid,yGrid,valMat);
If you want interpolation, you can convolve a Gaussian kernel (maybe 3x3) with valMat.