loop through element of meshgrid matlab - matlab

I am trying to loop through a meshgrid to create a matrix of vectors. If I have:
[x,y] = meshgrid(1:2,1:2)
can someone explain looping through each element to get a matrix which equals:
matrix =
[x(1,1) y(1,1)] [x(1,2) y(1,2)]
[x(2,1) y(2,1)] [x(2,2) y(2,2)]
thanks in advance

If you want a 2x4 matrix with the values of x and y interleaved, this will work:
matrix = zeros(2,4);
matrix(:,[1 3]) = x;
matrix(:,[2 4]) = y;
If instead you want a 2x2x2 matrix with x and y stacked, use cat:
matrix = cat(3,x,y);
This concatenates x and y along the third dimension.

Maybe you could arrange each pair of coordinates as one row:
[x,y] = meshgrid(1:2,1:2)
xy = [x(:) y(:)];
Thus:
>> xy =
1 1 %# xy(1,:) = [x(1,1),y(1,1)]
1 2 %# xy(2,:) = [x(2,1),y(2,1)]
2 1 %# xy(3,:) = [x(1,2),y(1,2)]
2 2 %# xy(4,:) = [x(2,2),y(2,2)]

Related

How to assign vectors (along the fourth dimension) to pre-specified subscripts

I have a matrix of x,y,z matrix coordinates as well as a matrix of row vectors corresponding to timeseries associated with these coordinates. E.g.
coordinates = [1 2 3; 57 89 22]; % Where the column 1 = x, column 2 = y, column 3 = z
timeseries = rand(2,200); % where each row corresponds to the timeseries of the coordinates in the same row in the coordinates matrix.
I want to build a 4D matrix containing these timeseries. Any unassigned coordinate should default to a vector of zeros. Currently I do this as follows:
M = zeros(100,100,100,200);
for ii = 1:size(coordinates,1)
M(coordinates(ii,1),coordinates(ii,2),coordinates(ii,3),:) = timeseries(ii,:);
end
This works, but I was wondering if there is a (more readable/efficient) method to write the for-loop in a single step. I've tried using logical arrays and indices, but it always fails because I'm assigning vectors, not scalars.
Here's a way using sub2ind. I haven't timed it:
sz = [100 100 100 200];
M = zeros(sz(1)*sz(2)*sz(3), sz(4));
ind = sub2ind(sz([1 2 3]), coordinates(:,1), coordinates(:,2), coordinates(:,3));
M(ind(:),:) = timeseries;
M = reshape(M, sz);
You can increase speed a little replacing sub2ind by manual computation:
sz = [100 100 100 200];
M = zeros(sz(1)*sz(2)*sz(3), sz(4));
ind = coordinates(:,1) + sz(1)*(coordinates(:,2)-1) + sz(1)*sz(2)*(coordinates(:,3)-1);
M(ind(:),:) = timeseries;
M = reshape(M, sz);

Access matrix values by X and Y coordinates

I have coordinates in an matrix (an image) that I want to change, I have the coordinates in the form of a x coordinates vector and a y coordinates vector. How do I change the values of only those coordinates.
I've tried to use the notation I(x,y) but it gives me all the possible combinations:
I = zeros(10,10);
x = [4 6 8];
y = [7 3 1];
I(x,y) = 1;
imshow(I);
gives me: while what I want to get is:
using sub2ind function like the following:
I(sub2ind(size(I),x,y)) = 1

surface plot in Matlab

I am trying to graph a surface with a diagonal matrix, the equation I am trying graph is f = x^TDx, x is a 2 by 1 vector and D is a 2 by 2 matrix.
Here is what have so far, but I keep getting error.
x = linspace(-10,10);
y = linspace(-10,10);
[X,Y] = meshgrid(x,y);
D = [1 0; 0 1];
f = #(x,y) [x,y]*D*[x,y].'; % [x,y] is 1 by 2
contour (X,Y,f(X,Y))
Can someone tell me how to get rid of the error? Thanks
Since x and y have the same length, your diagonal matrix D must be a square matrix of size n x n, with n equal to two times the length of your x or y vectors. The reason why you need to multiply the length by two is because the operation [x,y] concatenates the arrays horizontally thus duplicating one of the dimensions.
In this example D is the Identity matrix. See eye for more information.
x = linspace(-10,10); % x is 1x100
y = linspace(-10,10); % y is 1x100
[X,Y] = meshgrid(x,y); % X is 100x100 and Y is 100x100
D = eye(2*numel(x)); % D is 2*100x2*100 = 200x200
f = #(x,y) [x,y]*D*[x,y].'; % [X,Y] is 100x200 and [X,Y].' is 200x100
contour (X,Y,f(X,Y))
If you want D to be a random diagonal matrix, you can accomplish this combining diag with one of the Random Number Generation functions available, like for example randn.
On the previous example, replace D with the following instruction:
D = diag(randn(1,2*numel(x)));
You can also give the coefficients you choose to the diagonal matrix. To do so, you will need to create the vector of coefficients manually, making sure that it has the adequate length, so that it satisfies the conditions explained at the beginning of this post.
Try now replacing D with the following instructions:
v = 1:2*numel(x); % vector of coefficients: v = [1 2 ... 200]
D = diag(v);

Generate heatmap with coordinates and data stored in vectors

Let A be an n by 3 matrix, such that the first two columns are all ordered pairs of the form (5*i,5*i) for i from 1 to 200. The third column contains values from 0 to 1, which I will call intensities. I want to make a 1000 by 1000 plot so that the rectangle at (5*i,5*i) is shaded with intensity described by the third column entry.
I'm familiar with the heatmap function and imshow, but I don't see a way to include this "scaling by 5" to make a nice plot. And of course in general the x and y coordinates may not be scaled by the same amount.
Is there a nice way to do this in Matlab?
With imagesc it's actually pretty simple:
First some example data:
%// generate example data
ii = 1:200;
[xx,yy] = meshgrid(ii);
A(:,1) = 5*xx(:);
A(:,2) = 5*yy(:);
A(:,3) = randi([0,1],1,40000);
Actual answer
n = 200;
%// reshape data
D = reshape( A(:,3),n,n );
%// heatmap
imagesc(A(:,1),A(:,2),D)
colormap(gray)
caxis([0,1])
gives:
Important notice
If your coordinates are not sorted as required for imagesc you can sort them with:
A = sortrows(A,[2,1]);
Clown Example
%// original image
load clown
I = reshape(1:numel(X),size(X));
[R,C] = ind2sub(size(X),I);
A(:,1) = R(:);
A(:,2) = C(:);
A(:,3) = X(:);
D = reshape( A(:,3),200,320 );
figure(1)
subplot(1,3,1)
imagesc(A(:,1),A(:,2),D)
%// shuffled image -> shuffled data
shuffle = randperm(320*200);
A = A(shuffle,:);
D = reshape( A(:,3),200,320 );
subplot(1,3,2)
imagesc(A(:,1),A(:,2),D)
%// sorted image
A = sortrows(A,[2,1]);
D = reshape( A(:,3),200,320 );
subplot(1,3,3)
imagesc(A(:,1),A(:,2),D)
You see, even if your coordinates are sorted like a mess, you can rebuild the image with sortrows.
See this
function DrawHeatmap(X,Y,Z)
%DRAWHEATMAP Draw a 2D heatmap for (X,Y) coordinates whose values are in Z
% X, Y , Z must be columns
% By: Eng. Osama Talaat Abdel-Hafiz - PhD Student
% Egypt - Sept 2017
if size(X,2)==1 && size(Y,2)==1 && size(Z,2)==1
F = scatteredInterpolant(X,Y,Z); % create a function from interpolation
[X,Y] = meshgrid(min(X):0.1:max(X),min(Y):0.1:max(Y));
Z = F(X,Y);
contourf(X, Y, Z, linspace(floor(min(min(Z))),ceil(max(max(Z))),400), 'LineColor','none')
colorbar;
else
error('X, Y , Z must be columns')
end
end

MatLab--How would I generate an n-sided shape wher n >= 4

I'm new to Matlab but I know a bit about programming.
For class, we have been asked to generate a matrix that gives the vertices of a two dimensional n-sided shape where n>=4. Then, generate the vectors to connect the vertices. We were also given a hint: a vector for each segment can be found by adding the vectors drawn from the origin to each of two adjacent vertices.
I know how to create a matrix using A = [1 1; 1 2; 2 2; 2 1] but I'm not sure how to draw the vectors given this or any other matrix.
The plot() function looks promising, but I'm unsure how to use it with the matrix.
Thank you for any suggestions.
Btw, I'm using Matlab 2011a
I'm not exactly sure how your matrix represents your shape but you might for example let the x-coordinates of the shape be the first column of your array, then let the y-coordinates be the 2nd column, like:
A = [1 1; 1 2; 2 2; 2 1];
x = A(:,1);
y = A(:,2);
fill(x,y,'g');
axis([0 3 0 3]);
axis square;
Which in your case plots a square from the matrix A:
Or construct something a little more complicated like a pentagon:
theta = [0:pi/2.5:2*pi];
x = sin(theta);
y = cos(theta);
% your matrix is then:
B(:,1) = x;
B(:,2) = y;
B
figure;fill(x,y,'g');
axis square;
Which gives:
If you just want to plot the outline with plot (not fill the interior with fill), just remember you have to repeat the initial point at the end so that the polygonal line is closed:
A = [1 1; 1 2; 2 2; 2 1];
B = [A; A(1,:) ]; %// repeat first row at the end
plot(B(:,1),B(:,2))
axis equal %// same scale on both axes
axis([min(x)-.5 max(x)+.5 min(y)-.5 max(y)+.5]) %// larger axes for better display