Rearranging vectors into matrix - matlab

I have data and it is arranged in following order
Now you can see for every x value there are different y values and respectively some real and img values. x has a dimension m x 1 and y has a dimension n x 1. Now I want to arrange data in a new matrix in such a way that new matrix has a dimension of m x n. In other words the x will be my row and values of y will be my columns and correspondingly for each x and y the value comes into the new matrix as follows.
new_matrix(m,n)= real*exp{img}
i.e. For each x and y values the real part should multiply with exponential of imaginary part and comes into the new matrix.

MATLAB uses column-major indexing so if you create a matrix that is m x n and then fill it, it will fill down the rows first and then across the columns. Your is ordered in row-major order (and if it's not we can use sortrows to ensure that it is). We can then just compute the real * exp(imag) using the last two columns and reshape it to be n x m and then transpose it to get your m x n matrix.
data = [0 1 25 12
0 2 15 26
1 1 78 26
1 2 25 63
2 1 26 35
2 2 45 63
3 1 56 26
3 2 48 2];
% Ensure that the data is in the correct order
data = sortrows(data);
% Determine the size of the output matrix
m = numel(unique(data(:,1)));
n = numel(unique(data(:,2)));
% Compute real * exp(imag) and make it the correct shape
out = reshape(data(:,3) .* exp(data(:,4)), n, m).';
% 4.0689e+06 2.9359e+12
% 1.5267e+13 5.7345e+28
% 4.1236e+16 1.0322e+29
% 1.0961e+13 3.5467e+02

What you got is a sparse representation of a matrix. Using the sparse constructior is the simplest (but maybe not the fastest) way to get your matrix:
full(sparse(data(:,1)+1,data(:,2),data(:,3) .* exp(data(:,4))))

Related

Divide a matrix and its corresponding vector into submatrices and subvectors in MATLAB

I have two matrices X (122 x 125973) and Y (1 x 125973). I want to split in the same way X and Y into smaller matrices and vectors of 122 x 1024 (column division) in Matlab.
I have tried several methods (mat2cell, loops, etc), but I think I am missing the syntax. Any help ?
Note: 125973 can't be divided by 1024, so the last matrix (and vector) will the have the size of (122 x 21) (and (1 x 21) respectively). Thank you for your help!
Since your sub-matrices do not have equal size, you cannot put them in a 3D array (without NaN or zero padding). So you can use a cell. To do this with mat2cell you have to specify how many rows of the original matrix should be put in each individual entry of the cell:
X = rand(122,125973);
Y = rand(1,125973);
% your number of rows per 'block'
n = 1024;
% the number of cols per cell entry:
colDist = [repelem(n, floor(size(X,2)/n)) rem(size(X,2),n)];
Xcell = mat2cell(X, size(X,1), colDist);
Ycell = mat2cell(Y, size(Y,1), colDist);
Here repelem(n, floor(size(X,2)/n)) repeats n for the number of times n fits in the number of columns of X. Then I append the remainder for the number of columns at the end (rem(size(X,2),n)) of this division to this row vector colDist.
When calling mat2cell (mat2cell(X, rowDist, colDist)) the second argument rowDist should then contain the number of rows per cell entry, which for each cell entry will be equal to the number of rows in X or Y.
Alternatively, you can use a loop to divide the matrix and vector in sub-matrices and put them in the appropriate cell.
Xcell = cell(ceil(size(X,2)/n),1);
Ycell = cell(ceil(size(X,2)/n),1);
% put in the blocks of n rows
for k = 1:floor(size(X,2)/n)
indices = n*(k-1)+1:n*k;
Xcell{k} = X(:,indices);
Ycell{k} = Y(:,indices);
end
% and the remainder:
Xcell{end} = X(:, indices(end)+1:end);
Ycell{end} = Y(:, indices(end)+1:end);

matlab gridding using for loop

I have a 4032 X 102 matrix (first 2 columns are the coordinates). I would like to interpolate every column by a 48 X 84 meshgrid. It's working column-by-column, but it would be great if it can be done by one command (with a for loop maybe).
x = 1:84; y = 1:48;
[X,Y] = meshgrid(x,y);
Z = griddata(data(:,1),data(:,2),(:,3:102),X,Y'v4');
The input data is also grid data but not in matrix form. My goal is to create map(grid again) from this. So there are X, Y coordinates and values. Each column represent data of a map, and the values along the coordinates.
First 2 columns contain the coordinates of the data point. These are the first 2 row of a map with 4 cell spacing. Z is the gridded data matrix along the 48 x 84 grid.
Many thanks!
You can reshape a 4032x1 vector into a 48x84 2-D matrix:
reshape(vector, 48,84)
Since you have 102 of them, and they are already stored in a single matrix variable, you can now store each single matrix in the first two dimensions (1st dim has 48 elements and 2nd has 84) and all 102 matrices are indexed in the third dimension.
reshape(data, 48,84,102)

Fastest way to find a cross in a matrix

Definition:
A(i, j) = 1 is a midpoint of a cross if the elements
A(i-1, j) = 1
A(i+1, j) = 1
A(i, j+1) = 1
A(i, j-1) = 1.
Together the elements and the midpoint form a cross in a matrix A, where A is at least a 3-by-3 matrix and i, j ∈ ℕ\{0}.
Suppose the image above is the 8-by-8 matrix A with natural numbers 1, 2, 3 ... as elements. From this definition the matrix has a total of 3 crosses. The crosses have their midpoints on A(2,2), A(5, 4) and A(5, 5).
What I want to do is write a function that finds the number of crosses in the matrix A. I have an idea but I'm not sure it's the most optimal one. Here's the pseudocode for it:
ITERATE FROM row 2 TO row 7
ITERATE FROM column 1 TO column 8
IF current element contains 1
INCREMENT xcount by 1
IF xcount >= 3
CHECK IF counted 1:s is part of a cross
ELSE IF xcount IS NOT 0
SET xcount to 0
The idea is to iterate through every column from row 2 to row 7. If I find 3 consecutive 1:s on the same row I immediately check if the 1:s belongs to a cross. This should work, but imagine having a very large matrix A - how efficient would this code be in that situation? Couldn't this problem be solved using vector notation?
Any answer is very much appreciated. Thanks in advance!
Not near matlab at the moment, but this is what I'd do. Assuming A is binary (has only 0'a and 1's):
crs=[0 1 0 ; 1 1 1 ; 0 1 0]; % a minimal "cross" filter
C=conv2(A,crs./sum(crs(:)),'same'); % convolve A with it
[x y]=find(C>0.9); % find x,y positions of the crosses by looking
% for peak values of C
so you basically convolve with a "minimal" (normalized) cross (crs) and look for peaks using max. x and y are the coordinates of your cross positions. No need to use for loops, just the built in (and pretty fast) 2d convolution, and the max function.
The threshold condition C>0.9, is just to illustrate that there's need to be a threshold that is weighted by intensity of crs. In this case I have normalized crs in the colvolution line (crs/sum(crs(:))) so if A is a binary matrix as in the example, you find that the convolution of the minimal normalized cross will leave the value of the pixel where the cross is at 1, whereas other pixels will be less than 1 (that's why I arbitrarily chose 0.9) . So you can replace the threshold to C==1, if it's always a binary.
Another way to visulize the position of the cross is just to look at C.*(C==1). This will generate a matrix the size of A with 1s only where the crosses were...
EDIT:
For maximal speed, you may consider writing it as a one liner, for example:
[x y]=find(conv2(A,[0 1 0 ; 1 1 1 ; 0 1 0]./5,'same')==1);
Using bit masks:
ux = [false(size(A,1),1) (A(:,3:end) & A(:,2:end-1) & A(:,1:end-2)) false(size(A,1),1)]
uy = [false(1,size(A,2)); (A(3:end,:) & A(2:end-1,:) & A(1:end-2,:)); false(1, size(A,2))]
u = ux & uy
[x y] = find(u)

Merging Two Data set

My question is related to merging two matrices with different spacing on the field
Both matrices are in (frequency space domain (F-X)) and to illustrate lets consider :
Matrix One (A x B)
Matrix Two (A x C)
Where (A = 1500) is the frequency samples (they both share the same frequency samples number).
(B = 168 ) is the number of Receivers for the first data set (recording stations in the field) with spacing of 12 meters between B(1) and B(2), 12 meters between B(2) and B(3) and so on
(C = 196 ) is also the number of Receivers for the second data set (recording stations in the field) with different spacing than B. So C(1) to C(2) is 48 and C(2) to C(3) is 48 and so on.
The total length of receiver line in Matrix One is (168*12) = 2016 m.
The total length of receiver line in Matrix Two is (196*48) = 9408 m.
The line from matrix (one) sits on the middle part of line two.
Meaning they do over lap in many locations where both are present.(every forth receiver from the shorter line is overlapped by a receiver from the longer line)
I want to merge them (add them together) in a way where the final result represent the courser spacing (matrix two) added to it matrix A in the location where they overlap.
I hope I made this somehow clear
If A and B are your 2 matrices then merged would be the merged matrix. I used a size of 196x100 and 168x100 for the matrices just because I was to lazy to use 1500 ;).
C,D are integers ranging from 1 to the size of the first dimension.
A= randi(100, 168 ,100)+20;
B= randi(10, 196, 100);
C= 1:168; %ranging from 1 to number of receiver in Matrix 1(A)
D= 1:196; %ranging from 1 to number of receiver in Matrix 2(B)
C= C*12+4704; %Distance of each receiver to 0 and shifted to the middle of 2nd matrix
D= D*48; %Distance of each receiver to 0
A= [C', A]; %adding distance as first column to Matrix 1
B= [D', B]; %adding distance as first column to Matrix 2
C= [A;B]; %adding the 2 matrices
C=sortrows(C,1); %sorting the new matrix
merged = C(:,2:end); %deleting first column (distance)
What I am doing is generating the distance (C,D) appending them in column 1 appending the two matrices rowwise and sorting rowwise regarding the distance (new column 1). Then at the end I delete the distance because you didn't ask for it.
Just realized that your matrix is not 168x1500 but 1500x168, just convert it, using (A=A';)
If I'm understanding your question correctly, you want to add every 4th value of matrix 1 (I'll call this A) into matrix 2 (I'll call this B) at some defined position in the middle of 2. So we need to pick every 4th value of B and add it to A at some point of overlap p.
Here's how to select every 4th value of B along the 2nd dimension:
coarseB = B(:, 4:4:end);
Since matrices A and B are of different sizes, we have to expand the size of A with zeros so it can be added to B. It will help to know the size of coarseB along the 2nd dimension:
sizeB = size(B, 2);
coarseB = [zeros(1500, p - 1) coarseB zeros(1500, 168 - (p - 1) - sizeB)];
This will concatenate a zero array at the end and the beginning of coarseB to expand it to the size of A (1500 x 168).
Now coarseB can be added to A:
merged = coarseB + A;
Hope this helps!

Method to sum of the elements of different sized matrix in Matlab

Can anybody help me to find out the method to sum of the elements of different sized matrix in Matlab ?
Let say that I have 2 matrices with numbers.
Example:
A=[1 2 3;
4 5 6;
7 8 9]
B=[10 20 30;
40 50 60]
I wanna create matrix C filling with sum(absolute subtract of matrix A and B).
Example in MS Excel.
D10=ABS(D3-I3)+ABS(E3-J3)+ABS(F3-K3)
E10=ABS(D4-I3)+ABS(E4-J3)+ABS(F4-K3)
F10=ABS(D5-I3)+ABS(E5-J3)+ABS(F5-K3)
And then (Like above)
D11=ABS(D3-I4)+ABS(E3-J4)+ABS(F3-K4)
E11=ABS(D4-I4)+ABS(E4-J4)+ABS(F4-K4)
F11=ABS(D5-I4)+ABS(E5-J4)+ABS(F5-K4)
Actually A is a 30x8 matrix and B is a 10x8 matrix.
How can i write this in Matlab?
Code
%%// Spread out B to the third dimension so that the singleton
%%// second dimension thus created could be used with bsxfun for expansion in
%%// that dimension
t1 = permute(B,[3 2 1])
%%// Perform row-wise subtraction and then summing of their absolute values
%%// as needed
t2 = sum(abs(bsxfun(#minus,A,t1)),2)
%%// Since the expansion resulted in data in third dimension, we need to
%%// squeeze it back to a 2D data
out = squeeze(t2)'