I make point plots like this one:
But now I need to plot all the lines between the points as well to create rectangular mesh under a deformation (i.e. do the connection to the closest neighbors in x and y direction - not connect all the points with all the points).
How can I convince matlab/octave to do that?
The code I have used is here:
%T,H,W and k are defined above, it doesn't matter for the plot.
for ii=1:2:H
for jj=1:2:W
k=0.1;
x=jj;
y=ii;
U(ii,jj)=7*exp(0.05*(y-H))*cos(k*x-T);
V(ii,jj)=4*exp(0.1*(y-H))*sin(k*x-T);
X(ii,jj)=jj;
Y(ii,jj)=ii;
end
end
plot(X+U,Y+V,'k.');
A plot as you want it is easily done with mesh(X,Y,Z).
The problem with your code is that you have a lot of zeros in your matrices. These might be intentional. In that case I could provide another solution. But mesh() connects neighboring points in a matrix. Therefore having the 0 in every second line and row would connect every point to (0,0). The easiest way is to just let your ii,jj grow in steps of 1.
%T,H,W and k are defined above, it doesn't matter for the plot.
H = 20;
W = 40;
T = 2*pi;
for ii=1:1:H
for jj=1:1:W
k=0.1;
x=jj;
y=ii;
U(ii,jj)=7*exp(0.05*(y-H))*cos(k*x-T);
V(ii,jj)=4*exp(0.1*(y-H))*sin(k*x-T);
X(ii,jj)=jj;
Y(ii,jj)=ii;
end
end
plot(X+U,Y+V,'k.');
hold on
mesh(X+U, Y+V, zeros(size(X)));
Related
I have a set of xy coordinates in a matrix X = [x1,x2,... ; y1,y2,...]. The points come from finding the root of a function iteratively. I'd like to plot each coordinate on a Cartesian grid, but ideally have some way to distinguish the earlier coordinates from the later one. So for example, if I could plot each point, and have the colour get a bit darker with each point, then the viewer would be able to see how the points actually do converge. Is there a way to specify this somehow?
There should be so many ways to do this, as it is a simple task, BTW.
Example:
hold on
k = 0;
while (true)
k = k+1;
if k == 10; break; end % just to stop loop
r = k/10; % something linked to the found root
plot(k,k,'*','Color',[r,r,r]); % your plot
end
So basically, you link r to the found root or to something that shows the distance from the root.
This solution should give you idea, hopefully.
I'm having some difficulty getting a simple script to work. The goal is to rotate an array of points about the origin using some angle. However, the code I'm using seems not to maintain the magnitude of the vector.
Im using a array where the first column is x coordinate and the second is y coordinate:
for ii=1:1000
angleRads=rand()*2*pi;
randRotPoints(ii,1)=1*cos(angleRads)-0*sin(angleRads);
randRotPoints(ii,2)=0*cos(angleRads)+1*sin(angleRads);
end
figure;
scatter(randRotPoints(:,1),randRotPoints(:,2));
lengths1=sqrt(randRotPoints(:,1).^2+randRotPoints(:,2).^2);
for ii=1:1000
angleRads=rand()*2*pi;
randRotPoints(ii,1)=randRotPoints(ii,1)*cos(angleRads)-randRotPoints(ii,2)*sin(angleRads);
randRotPoints(ii,2)=randRotPoints(ii,2)*cos(angleRads)+randRotPoints(ii,1)*sin(angleRads);
end
figure;
scatter(randRotPoints(:,1),randRotPoints(:,2));
lengths2=sqrt(randRotPoints(:,1).^2+randRotPoints(:,2).^2);
After the first loop, there is a coordinates of magnitude of 1 and random orientation. This is confirmed via the scatter plot and the lengths1 array is all 1s.
However, the second loop that attempts to rotate those coordinates by a second random angle results in seemingly randomly located coordinates (based on the scatter plot), and the lengths are no longer all 1.
Please help me figure out where I've gone wrong with this rotation code. I know that this isn't the most efficient code in terms of performance or number of lines, if you want to provide a better way to do it in terms of efficiency that is fine, but please also state what would be needed to fix the code in its current format as well.
Thanks.
In your second loop you have
randRotPoints(ii,1)=randRotPoints(ii,1)*cos(angleRads)-randRotPoints(ii,2)*sin(angleRads);
randRotPoints(ii,2)=randRotPoints(ii,2)*cos(angleRads)+randRotPoints(ii,1)*sin(angleRads);
i.e. you use the overwritten (rotated) x coordinate when computing the y. Try saving the randRotPoints(ii,:) vector before rotating it, and using the saved value on the right hand side.
As for making it more efficient:
The more readable solution
You can make the code much more readable by explicitly defining the rotation matrix for each point
for ii=1:1000
angleRads=rand()*2*pi;
rotmat=[cos(angleRads) -sin(angleRads); sin(angleRads) cos(angleRads)];
randRotPoints(ii,:)=rotmat*[1; 0];
%note that this is equivalent to
%randRotPoints(ii,:)=[cos(angleRads); sin(angleRads)];
end
figure;
scatter(randRotPoints(:,1),randRotPoints(:,2));
lengths1=sqrt(randRotPoints(:,1).^2+randRotPoints(:,2).^2);
for ii=1:1000
angleRads=rand()*2*pi;
rotmat=[cos(angleRads) -sin(angleRads); sin(angleRads) cos(angleRads)];
randRotPoints(ii,:)=rotmat*(randRotPoints(ii,:).');
end
figure;
scatter(randRotPoints(:,1),randRotPoints(:,2));
lengths2=sqrt(randRotPoints(:,1).^2+randRotPoints(:,2).^2);
In order to spare some code-duplication you could also define a rotmatfun=#(angleRads) [cos(angleRads) -sin(angleRads); sin(angleRads) cos(angleRads); function, then you can just say rotmat=rotmatfun(angleRads); in the loops.
The more efficient solution
You can do away with your loops entirely by making use of the vectorized notation:
N=1000; %number of points
angleRads=rand(N,1)*2*pi;
randRotPoints=[1*cos(angleRads)-0*sin(angleRads), ...
0*cos(angleRads)+1*sin(angleRads)]; %matrix of size [N,2]
figure;
scatter(randRotPoints(:,1),randRotPoints(:,2));
lengths1=sqrt(randRotPoints(:,1).^2+randRotPoints(:,2).^2);
angleRads=rand(N,1)*2*pi;
randRotPoints=[randRotPoints(:,1).*cos(angleRads)-randRotPoints(:,2).*sin(angleRads), ...
randRotPoints(:,2).*cos(angleRads)+randRotPoints(:,1).*sin(angleRads)];
figure;
scatter(randRotPoints(:,1),randRotPoints(:,2));
lengths2=sqrt(randRotPoints(:,1).^2+randRotPoints(:,2).^2);
I am trying to make a simple plot (for this example doing a plot of y=x^2 will suffice) where I want to set the colors of the points based on their magnitude given some colormap.
Following along my simple example say I had:
x = 1:10;
y = x.^2;
Use gscatter(x,y,jet(10)); legend hide; colorbar which produces a plot with the points colored but the colorbar does not agree with the colored values. (Can't post picture as this is my first post). Using a caxis([1,100]) command gives the right range but the colors are still off.
So I have two questions:
(1) How can I fix the colors to fit to a colorbar given a range? In my real data, I am looking at values that range from -50 to 50 in some instances and have many more data points.
(2) I want to create a different plot with the same points (but on different axes) and I want the colors of each point on this new plot to have the same colors as their counterparts in the previous plot. How can I, programmatically, extract the color from each point so I can plot it on two different sets of axes?
I would just move the points into a matrix and do an imagesc() command but they aren't spaced as integers or equally so simple scaling wouldn't work either.
Thanks for any help!
Regarding you first question, you need to interpolate the y values into a linear index to the colormap. Something like:
x = 1:10;
y = x.^4;
csize = 128;
cmap = jet(csize);
ind = interp1(linspace(min(y),max(y),csize),1:csize,y,'nearest');
scatter(x,y,14,cmap(ind,:),'filled')
colorbar
caxis([min(y) max(y)])
Using interp1 in this case is an overkill; you could calculate it directly. However, I think in this way it is clearer.
I think it also answers your 2nd question, since you have the index of the color of each data point, so you can use it again in the same way.
I'm trying to plot several signals in one graph and i would like to restrict them and sort of minimize it so all my signals will be clear (more or less).
I have no idea how to do it. I'm adding an image so what i need to do will be clearer.
My data changes but in general it's the mean intensity of each column of a certain area in an intensity image.I tried to do it like with the same idea as you but i don't get the right plot as i wanted. A is the relevant matrix,b is the matrix with shifted values:
for i=1:20
b(i,:)=A(i,:)+(100*i);
plot(b(i,:))
hold on
end
I will also add 2 images: one is the plot of all the 20 signals that i get and the other one is the plot of only the first signal. I don't understand why do they look so different.
You can try something like that :
x = [1:100]; %Distance 1 to 100
y = F(x) % Your first function (signal)
y2 = 0.5*G(x) % Your second function (signal)
plot(x,y,x,y2); % plot both function in a single plot.
hleg1 = legend('Intensity t1,'Intensity t27');
So you have your signal at intensity t27 half cut for each value ( 0.5 ), so it shift down.
I've got a series of XY point pairs in MATLAB. These pairs describe points around a shape in an image; they're not a function, meaning that two or more y points may exist for each x value.
I can plot these points individually using something like
plot(B(:,1),B(:,2),'b+');
I can also use plot to connect the points:
plot(B(:,1),B(:,2),'r');
What I'm trying to retrieve are my own point values I can use to connect the points so that I can use them for further analysis. I don't want a fully connected graph and I need something data-based, not just the graphic that plot() produces. I'd love to just have plot() generate these points (as it seems to do behind the scenes), but I've tried using the linseries returned by plot() and it either doesn't work as I understand it or just doesn't give me what I want.
I'd think this was an interpolation problem, but the points don't comprise a function; they describe a shape. Essentially, all I need are the points that plot() seems to calculate; straight lines connecting a series of points. A curve would be a bonus and would save me grief downstream.
How can I do this in MATLAB?
Thanks!
Edit: Yes, a picture would help :)
The blue points are the actual point values (x,y), plotted using the first plot() call above. The red outline is the result of calling plot() using the second approach above. I'm trying to get the point data of the red outline; in other words, the points connecting the blue points.
Adrien definitely has the right idea: define a parametric coordinate then perform linear interpolation on the x and y coordinates separately.
One thing I'd like to add is another way to define your parametric coordinate so you can create evenly-spaced interpolation points around the entire shape in one pass. The first thing you want to do, if you haven't already, is make sure the last coordinate point reconnects to the first by replicating the first point and adding it to the end:
B = [B; B(1,:)];
Next, by computing the total distance between subsequent points then taking the cumulative sum, you can get a parametric coordinate that makes small steps for points close together and larger steps for points far apart:
distance = sqrt(sum(diff(B,1,1).^2,2)); %# Distance between subsequent points
s = [0; cumsum(distance)]; %# Parametric coordinate
Now, you can interpolate a new set of points that are evenly spaced around the edge along the straight lines joining your points using the function INTERP1Q:
sNew = linspace(0,s(end),100).'; %'# 100 evenly spaced points from 0 to s(end)
xNew = interp1q(s,B(:,1),sNew); %# Interpolate new x values
yNew = interp1q(s,B(:,2),sNew); %# Interpolate new y values
These new sets of points won't necessarily include the original points, so if you want to be sure the original points also appear in the new set, you can do the following:
[sAll,sortIndex] = sort([s; sNew]); %# Sort all the parametric coordinates
xAll = [B(:,1); xNew]; %# Collect the x coordinates
xAll = xAll(sortIndex); %# Sort the x coordinates
yAll = [B(:,2); yNew]; %# Collect the y coordinate
yAll = yAll(sortIndex); %# Sort the y coordinates
EXAMPLE:
Here's an example to show how the above code performs (I use 11 pairs of x and y coordinates, one of which is repeated for the sake of a complete example):
B = [0.1371 0.1301; ... %# Sample data
0.0541 0.5687; ...
0.0541 0.5687; ... %# Repeated point
0.0588 0.5863; ...
0.3652 0.8670; ...
0.3906 0.8640; ...
0.4090 0.8640; ...
0.8283 0.7939; ...
0.7661 0.3874; ...
0.4804 0.1418; ...
0.4551 0.1418];
%# Run the above code...
plot(B(:,1),B(:,2),'b-*'); %# Plot the original points
hold on; %# Add to the plot
plot(xNew,yNew,'ro'); %# Plot xNew and yNew
I'd first define some parametric coordinate along the different segments (i.e. between the data points)
s = 1:size(B,1);
Then, just use interp1 to interpolate in s space. e.g. If you want to generate 10 values on the line between data point 5 and 6 :
s_interp = linspace(5,6,10); % parametric coordinate interpolation values
x_coord = interp1(s,B(:,1),s_interp,'linear');
y_coord = interp1(s,B(:,2),s_interp,'linear');
This should do the trick.
A.
Actually there is a MATLAB function "improfile", which might help you in your problem. Lets say these are the 4 coordinates which you want to find the locations between these coordinates.
xi=[15 30 20 10];
yi=[5 25 30 50];
figure;
plot(xi,yi,'r^-','MarkerSize',12)
grid on
Just generate a random image and run the function
n=50; % total number of points between initial coordinates
I=ones(max([xi(:);yi(:)]));
[cx,cy,c] = improfile(I,xi,yi,n);
hold on, plot(cx,cy,'bs-','MarkerSize',4)
Hope it helps