Randomly select Elements of 4D matrix in Matlab - matlab

I have a 4D matrix with dimensions 7x4x24x10 (Lets call it main_mat). I want to get a matrix of size 7x4x24 (rand_mat) so that each element of this (rand_mat) matrix is actually a uniformly random draw from the main matrix (main_mat). I am sorry if I have not put the question clearly, so I try to explain:
I have a stack of 24 sheets of 7x4 elements, and I have 10 such stacks. What I want is that I get a single stack of 24 sheets of 7x4 elements in such a way that every element out of resultant single stack is uniformly randomly drawn from exactly same sheet number from within 10 stacks. How can I do it without using loops?

If I am interpreting what you want correctly, for each unique 3D position in this matrix of 7 x 4 x 24, you want to be sure that we randomly sample from one out of the 10 stacks that share the same 3D spatial position.
What I would recommend you do is generate random integers that are from 1 to 10 that is of size 7 x 4 x 24 long, then use sub2ind along with ndgrid. You can certainly use randi as you have alluded to in the comments.
We'd use ndgrid to generate a grid of 3D coordinates, then use the random integers we generated to access the fourth dimension. Given the fact that your 4D matrix is stored in A, do something like this:
rnd = randi(size(A,4), size(A,1), size(A,2), size(A,3));
[R,C,D] = ndgrid(1:size(A,1), 1:size(A,2), 1:size(A,3));
ind = sub2ind(size(A), R, C, D, rnd);
B = A(ind);
Bear in mind that the above code will work for any 4D matrix. The first line of code generates a 7 x 4 x 24 matrix of random integers between [1,10]. Next, we generate a 3D grid of spatial coordinates and then use sub2ind to generate column-major indices where we can sample from the matrix A in such a way where each unique 3D spatial location of the matrix A only samples from one chunk and only one chunk. We then use these column-major indices to sample from A to produce our output matrix B.

This problem might not be solvable without the use of loops. One way that could work is:
mainMatrix = ... (7x4x24x10 matrix)
randMatrix = zeros(mainMatrix(:,1,1,1), mainMatrix(1,:,1,1), mainMatrix(1,1,:,1))
for x = 1:length(mainMatrix(:,1,1,1))
for y = 1:length(mainMatrix(1,:,1,1))
for z = 1:length(mainMatrix(1,2,:,1))
randMatrix(x,y,z) = mainMatrix(x,y,z,randi(10))
end
end
end

Related

How to sort rows of a matrix based on the costrain of another matrix?

The 6 faces method is a very cheap and fast way to calibrate and accelerometer like my MPU6050, here a great description of the method.
I made 6 tests to calibrate the accelerometer based on the g vector.
After that i build up a matrix and in each row is stored the mean of each axis expressed in m/s^2, thanks to this question i automatically calculated the mean for each column in each file.
The tests were randomly performed, i tested all the six positions, but i didn't follow any path.
So i sorted manually the final matrix, based on the sort of the Y matrix, my reference matrix.
The Y elements are fixed.
The matrix manually sorted is the following
Here how i manually sorted the matrix
meanmatrix=[ax ay az];
mean1=meanmatrix(1,:);
mean2=meanmatrix(2,:);
mean3=meanmatrix(3,:);
mean4=meanmatrix(4,:);
mean5=meanmatrix(5,:);
mean6=meanmatrix(6,:);
meanmatrix= [mean1; mean3; mean2; mean4;mean6;mean5];
Based on the Y matrix constrain how can sort my matrix without knwowing "a priori" wich is the test stored in the row?
Assuming that the bias on the accelerometer is not huge, you can look at the rows of your matrix and see with which of the rows in your Y matrix matches.
sorted_meanmatrix = zeros(size(meanmatrix));
for rows = 1:length(Y)
% Calculates the square of distance and see which row has a nearest distcance
[~,index] = min(sum((meanmatrix - Y(rows,:)).^2, 2));
sorted_meanmatrix(rows,:) = meanmatrix(index,:);
end

Using MATLAB, is there a way to get a 2D visualisation of data points that are in 6D space?

Part of an assignment of mine is to provide a 2D visualisation (plots) of some of my data points that are stored in a matrix. I'm slightly confused because the data is actually in 6D space (i.e. each row has 6 columns like 0 1 0 8 8 2).
Is there something I'm missing or does this genuinely not make sense? Is this something MATLAB can do?
Edit: Is something like this possible?
Though I wouldn't consider it visualizing 6D data, you can get the linked plot with a simple call to plot:
A = rand(6);
x = 1:6;
plot(x,A'); % Transpose A to plot rows since it's square, see plot documentation
Which produces the following:
From the documentation:
If one of X or Y is a vector and the other is a matrix, then the
matrix must have dimensions such that one of its dimensions equals the
vector length. If the number of matrix rows equals the vector length,
then the plot function plots each matrix column versus the vector. If
the number of matrix columns equals the vector length, then the
function plots each matrix row versus the vector. If the matrix is
square, then the function plots each column versus the vector.
Simply use:
surf(2Dmatrix)
You can read more here: http://uk.mathworks.com/help/matlab/ref/surf.html
If your matrix is 2D image, simply use
figure; imshow(2Dmatrix, [])
If you leave the square bracket empty, the limit will be automatic. When the figure is displayed you can change it to different colormap by Edit > Colormap.

covariance of a 400 50X50 matrix of matlab

I want to calculate covariance of 400 50 X 50 matrices using loop so when I tried..
for i=t-9:t+59
for j=r-9:r+59
a(:,:,p)=vidFrames2(i:(i+49),j:(j+49));
b(:,:,p)=cov3d(double(a));
p=p+1;
end
end
this code I got error "Assignment has more non-singleton rhs dimensions than non-singleton subscripts"
but when i want to remove this error by squeeze function in this code,
b(p,:)=cov3d(squeeze(double(a)));
I got "Subscripted assignment dimension mismatch."
how can I calculate covariance of 3d matrix....the cov3d function is-
function xy = cov3d(x)
[m,n,r] = size(x);
if m==1
x=zeros(n,n,r,class(x));
else
xc=bsxfun(#minus,x,sum(x,1)/m);
for i=1:r
xci=xc(:,:,i);
xy(:,:,i)=xci'*xci;
end
xy=xy/(m-1);
end
actually i wanted 400 number of covariance matrices stored in a variable.after this change i only get one covariance matrix.actually i am working on a frame where i am storing the initial coordinate values in i and j of a 50 X 50 matrix. then i want to get the pixel values of the 10 X 10 neighbourhood in the form of 50 X 50 matix. that means if i entered the initial coordinate as (100,100), then i want to get pixel values stored within region (91,91)(91,141)(141,91)(141,141).then store the covariance value of this matix. then again it will find the pixel values of the region (92,91),(142,91)(92,141),(142,141)and so on and covers the whole area..so if i cover the whole area then i think i will get total 400 matrices.and i want to store the covariance value of all the regions,.. today i changed the upper limit of the for loops to i=t-9:t+60 and j=r-9:r+60 but i did not get 400 covariance matrices
A few comments about your code:
cov3d is designed to return a 3D matrix, where the input is also a 3D matrix that calculates the covariance for each slice in this 3D matrix. From your code, the outer for loops (indices i and j) go from t-9 to t+59 in steps of 1 for each variable. As such, the pair of loops will execute ((t+59) - (t-9) + 1)^2 = 69^2 = 4761 times. I'm assuming that at each iteration, you are extracting a 2D matrix located at a which is why you initially said 400 times. You basically want to extract 400 matrices, but you are actually extracting 4761 matrices. Make sure a is properly declared to account for this many elements.
a(:,:,p)=vidFrames2(i:(i+49),j:(j+49)); accesses one slice, yet b(:,:,p)=cov3d(double(a)); is accessing the entire 3D matrix of a. Therefore, you will get a 3D matrix as the output of cov3d, yet you are trying to assign this to a single slice in b. What you should probably do is create your a matrix first, then make one call to cov3d when you're done.
Therefore, try changing your code to this:
%// Create `a` matrix first
for i=t-9:t+59
for j=r-9:r+59
a(:,:,p)=vidFrames2(i:(i+49),j:(j+49));
p=p+1;
end
end
%// Now call cov3d
b = cov3d(double(a));
Hopefully this will work the way you intended your code to originally work.

plotting multivariate data along eigenvectors

I have a data matrix contains 18 samples, each with 12 variables, D(18,12). I performed k-means clustering on the data to get 3 clusters. I want to visualize this data in 2 dimensions, specifically, along the 2 eigenvectors corresponding to the largest eigenvalues of a specific matrix, B. So, I create the plane spanned by two eigenvectors corresponding to the largest two eigenvalues:
[V,EA]=eig(B);
e1=V(:,11);
e2=V(:,12);
for i=1:12
E(i,1)=e1(i);
E(i,2)=e2(i);
end
Eproj=E*E';
where e1 and e2 are the eigenvectors, and E is a matrix containing those column vectors. At this point, I'm kind of stuck.
I recognize that e1 and e2 are orthogonal in this 12-d space, but I have no idea how this can reduce to two dimensions so I can plot it.
I believe that the projection of a data sample onto the plane would be:
Eproj*D(i,:)
for i=1...18, but I'm not sure where to go from here to plot my clusters. When I do the projection, its still in 12 dimensions.
Principal Component Analysis can help you to transform the data into 2D using the Eigenvectors.
coeff = princomp(B);
Bproj = B * coeff(:,1:2);
figure
plot(Bproj(:,1),Bproj(:,2),'*')
If you have the labels you can use the "scatter" function for a better visual. Or you can reduce the dimensionality to 3 and use "scatter3" function.

I want to plot a function in 3d in matlab

I have a function, X. It has inputs t and d.
X generates a 3x1 array, effectively an X,Y,Z tuple representing a point in 3-dimensional space.
I want to generate a plot for all values of t and d, given that 0 < t < 360 and 0 < d < 5. (They are not vectors.)
Currently I'm doing:
plot3(X(1),X(2),X(3),'.');
grid on
Which gives me just the one point in space. How should I go about doing this?
plot3(X(1),X(2),X(3),'.') is simply plotting the point generated by one pair of values for t and d.
You will want to generate an 3xN matrix for all the values of t and d that you want, perhaps using the linspace function to generate all the values of t and d that you want to plot.
Another option would be to use the ezsurf function as follows:
ezsurf('t+d',[0 360 0 5])