Plot several lines in Matlab without for-loop - matlab

In Matlab I have two Nx3 matrices P and Q and each line represents a point.
I want to plot lines between the points that are in the same row of the matrices.
Following Code does it:
for i=1:N
plot3( [P(i,1) Q(i,1)], ...
[P(i,2) Q(i,2)], ...
[P(i,3) Q(i,3)] )
end
Is there a way to do it without a for-loop?
If I give plot3 the points just as vectors, Matlab draws lines between Q(i,:) and P(i+1,:) in addition to the lines I want.

Try
plot3([P(:, 1) Q(:, 1)]', ...
[P(:, 2) Q(:, 2)]', ...
[P(:, 3) Q(:, 3)]')
If you feed a matrix to the Matlab plotting functions, each column corresponds to one line drawn.

Probably you want this:
h = quiver3(P(:,1), P(:,2), P(:,3), Q(:,1), Q(:,2) , Q(:,3),0);
set(h,'ShowArrowHead','off');

Related

MATLAB - scatter plot of a vector by a matrix?

I'm very new to Matlab. I'm trying to plot X, where X is an 100x1 vector, against Y, which is an 100x10 matrix. I want the result to be X vs 10 different Y values all in the same graph, different colors for each column. The only way I can think of plotting each column of this matrix is by using the hold command, but then I have to split it up so I get each column individually. Is there an easy way to do this?
Use repmat to expand X to be the same size as Y. Try plotting them with plot(X,Y) and if it looks strange, transpose each one (plot(X',Y')).
You can use linespec arguments to select linestyle, marker style, etc. For example, plot(X,Y,'.') would indicate a point at each vertex with no connecting lines.
You don't need to use repmat, just use plot instead of scatter:
plot(X,Y,'o')
Here's an example:
% some arbitrary data:
X = linspace(-2*pi,2*pi,100).'; % size(X) = 100 1
Y = bsxfun(#plus,sin(X),rand(100,10)); % size(Y) = 100 10
% you only need the next line:
plot(X,Y,'o')
legend('show')

Plotting rows of points in Matlab

So I'm still getting used to Matlab and am having a bit of trouble with plotting. I have a cell which contains a list of points in each row. I want to plot each row of points in a different colour on the same graph so I can compare them. The catch is that I need to make this work for an unknown number of points and rows (ie the number of points and rows can change each time I run the program).
So for example, I might have my cell array A:
A = {[0,0], [1,2], [3,4]; [0,0] [5,6], [9,2]}
and I want to plot the points in row 1 against their index (so a 3D graph) and then have the points in row 2 on the same graph in a different colour. The rows will always be the same length. (Each row will always have the same number of points). I've tried a few different for loops but just can't seem to get this right.
Any help in sending me in the right direction would be greatly appreciated!
The fact that the number of points and rows can change with each iteration should not pose much of a problem. I would suggest using the size function before your plot loops (size(A,1) and size(A,2)) to get the dimensions of the matrix.
Once you have the size of the matrix, loop through the dimensions and plot the lines on the same plot using holdon, and then finally just make the line color a function of the dimensions as you loop through so that you always have a different line color
You could just convert it to a matrix and plot it directly:
% Some dummy data - format a little different from your example
% to allow for different numbers of elements per row
A = {[0,0, 1,2, 3,4]; [0,0, 5,6]};
% Figure out how many columns we need in total
maxLen = max(cellfun(#length, A));
% Preallocate
Amat = NaN(size(A, 1), maxLen);
% Copy data
for n = 1:size(A, 1)
curA = A{n};
Amat(n, 1:length(curA)) = curA;
end
% Generate 1:N vector repeated the correct number of times (rows)
x = repmat(1:size(Amat, 2), size(Amat, 1), 1);
plot(x, Amat)
Edit: You mentioned a 3D graph at some point in your post. The above won't plot a 3D graph, so here's something that will:
% Generate Amat as above
% Then:
[X, Y] = meshgrid(1:size(Amat, 1), 1:size(Amat, 2));
surf(X, Y, Amat.'); % OR: plot3(X, Y, Amat.');
I'm not sure this is exactly what you want, but your question is slightly unclear on exactly what kind of graph you want out of this. If you just want coloured lines on your plot, you can use plot3 instead of surf, but IMHO surf will probably give you a clearer plot for this kind of data.

extract line of image (matrix)

I load images in matlab and work with them as double matrices.
Now I want to extract the data values across a straight line from one point of the image to another. This line however does not equal to a column or row (that would be easy).
How can I do that with matlab?
A line obeys the eq of the line y=a*x+b. Here x and y are coordiantes of the image. So if you want a line defined by two points (x1,y1) -> (x2,y2), the slope a is (y2-y1)/(x2-x1) and b=y1-a*x1. So next , select points in the matrix the obey the eq of the line as follows:
Create data and end points:
m=peaks(50);
x1=5 ; x2=42;
y1=21; y2=29;
calculate ew of line parameters:
a=(y2-y1)/(x2-x1);
b=y1-a*x1;
define the line:
x=x1:x2;
y=round(a*x+b);
select the proper matrix elements using linear indexing:
ind=sub2ind(size(m),y,x)
plot:
subplot(2,1,1)
imagesc(m); hold on
colormap(bone)
line([x1 x2],[y1 y2],'Color',[1 0 0]);
subplot(2,1,2)
plot(m(ind))

plot from data not a function

If you plot
sin(x*y)
you see some lines.
Now if u have all coordinates of all points of these lines and want to plot theme
(connecting dots without using sin(x*y) function), how is possible?
by this codes, i try to obtain coordinates of each 'x'(beta-bar) for each 'lam' and
save roots in a matrix.
clc; clear;
lmin=0.8; lmax=2.5;
bmin=1; bmax=1.5;
lam=linspace(lmin,lmax,100);
for n=length(lam):-1:1
increment=0.001; tolerence=1e-14; xstart=bmax-increment;
x=xstart;
dx=increment;
m=0;
while x > bmin
while dx/x >= tolerence
if sign(f(lam(n),x))*sign(f(lam(n),x-dx))<0
dx=dx/2;
else
x=x-dx;
end
end
m=m+1;
r(m,n)=x;
dx=increment;
x=0.999*x;
end
end
figure
hold on,plot(lam,r(1,:),'b')
plot(lam,r(2,:),'c')
plot(lam,r(3,:),'r')
xlim([lmin,lmax]);ylim([bmin,bmax]),
xlabel('\lambda(\mum)'),ylabel('\beta-bar')
and
function y=f(x,y)
y=sin(4*x*y);
end
what is wrong with it?
how to separately plot each line?
Use plot(X1,Y1,...,Xn,Yn)
See link for more details
http://www.mathworks.com/help/techdoc/ref/plot.html
use the plot() command. From the Matlab docu ('help plot' on the command line):
'PLOT(X,Y) plots vector Y versus vector X. If X or Y is a matrix,
then the vector is plotted versus the rows or columns of the matrix,
whichever line up. If X is a scalar and Y is a vector, disconnected
line objects are created and plotted as discrete points vertically at
X.'
So while plot(sin(X,Y)) used the plot(X) overload of the function, you will use the plot(X,Y) overload.

maybe matrix plot!

for an implicit equation(name it "y") of lambda and beta-bar which is plotted with "ezplot" command, i know it is possible that by a root finding algorithm like "bisection method", i can find solutions of beta-bar for each increment of lambda. but how to build such an algorithm to obtain the lines correctly.
(i think solutions of beta-bar should lie in an n*m matrix)
would you in general show the methods of plotting such problem? thanks.
one of my reasons is discontinuity of "ezplot" command for my equation.
ok here is my pic:
alt text http://www.mojoimage.com/free-image-hosting-view-05.php?id=5039TE-beta-bar-L-n2-.png
or
http://www.mojoimage.com/free-image-hosting-05/5039TE-beta-bar-L-n2-.pngFree Image Hosting
and my code (in short):
h=ezplot('f1',[0.8,1.8,0.7,1.0]);
and in another m.file
function y=f1(lambda,betab)
n1=1.5; n2=1; z0=120*pi;
d1=1; d2=1; a=1;
k0=2*pi/lambda;
u= sqrt(n1^2-betab^2);
wb= sqrt(n2^2-betab^2);
uu=k0*u*d1;
wwb=k0*wb*d2 ;
z1=z0/u; z1_b=z1/z0;
a0_b=tan(wwb)/u+tan(uu)/wb;
b0_b=(1/u^2-1/wb^2)*tan(uu)*tan(wwb);
c0_b=1/(u*wb)*(tan(uu)/u+tan(wwb)/wb);
uu0= k0*u*a; m=0;
y=(a0_b*z1_b^2+c0_b)+(a0_b*z1_b^2-c0_b)*...
cos(2*uu0+m*pi)+b0_b*z1_b*sin(2*uu0+m*pi);
end
fzero cant find roots; it says "Function value must be real and finite".
anyway, is it possible to eliminate discontinuity and only plot real zeros of y?
heretofore,for another function (namely fTE), which is :
function y=fTE(lambda,betab,s)
m=s;
n1=1.5; n2=1;
d1=1; d2=1; a=1;
z0=120*pi;
k0=2*pi/lambda;
u = sqrt(n1^2-betab^2);
w = sqrt(betab^2-n2^2);
U = k0*u*d1;
W = k0*w*d2 ;
z1 = z0/u; z1_b = z1/z0;
a0_b = tanh(W)/u-tan(U)/w;
b0_b = (1/u^2+1/w^2)*tan(U)*tanh(W);
c0_b = -(tan(U)/u+tanh(W)/w)/(u*w);
U0 = k0*u*a;
y = (a0_b*z1_b^2+c0_b)+(a0_b*z1_b^2-c0_b)*cos(2*U0+m*pi)...
+ b0_b*z1_b*sin(2*U0+m*pi);
end
i'd plotted real zeros of "y" by these codes:
s=0; % s=0 for even modes and s=1 for odd modes.
lmin=0.8; lmax=1.8;
bmin=1; bmax=1.5;
lam=linspace(lmin,lmax,1000);
for n=1:length(lam)
increment=0.001; tolerence=1e-14; xstart=bmax-increment;
x=xstart;
dx=increment;
m=0;
while x > bmin
while dx/x >= tolerence
if fTE(lam(n),x,s)*fTE(lam(n),x-dx,s)<0
dx=dx/2;
else
x=x-dx;
end
end
if abs(real(fTE(lam(n),x,s))) < 1e-6 %because of discontinuity some answers are not correct.%
m=m+1;
r(n,m)=x;
end
dx=increment;
x=0.99*x;
end
end
figure
hold on,plot(lam,r(:,1),'k'),plot(lam,r(:,2),'c'),plot(lam,r(:,3),'m'),
xlim([lmin,lmax]);ylim([1,1.5]),
xlabel('\lambda(\mum)'),ylabel('\beta-bar')
you see i use matrix to save data for this plot.
![alt text][2]
because here lines start from left(axis) to rigth. but if the first line(upper) starts someplace from up to rigth(for the first figure and f1 function), then i dont know how to use matrix. lets improve this method.
[2]: http://www.mojoimage.com/free-image-hosting-05/2812untitled.pngFree Image Hosting
Sometimes EZPLOT will display discontinuities because there really are discontinuities or some form of complicated behavior of the function occurring there. You can see this by generating your plot in an alternative way using the CONTOUR function.
You should first modify your f1 function by replacing the arithmetic operators (*, /, and ^) with their element-wise equivalents (.*, ./, and .^) so that f1 can accept matrix inputs for lambda and betab. Then, run the code below:
lambda = linspace(0.8,1.8,500); %# Create a vector of 500 lambda values
betab = linspace(0.7,1,500); %# Create a vector of 500 betab values
[L,B] = meshgrid(lambda,betab); %# Create 2-D grids of values
y = f1(L,B); %# Evaluate f1 at every point in the grid
[c,h] = contour(L,B,y,[0 0]); %# Plot contour lines for the value 0
set(h,'Color','b'); %# Change the lines to blue
xlabel('\lambda'); %# Add an x label
ylabel('$\overline{\beta}$','Interpreter','latex'); %# Add a y label
title('y = 0'); %# Add a title
And you should see the following plot:
Notice that there are now additional lines in the plot that did not appear when using EZPLOT, and these lines are very jagged. You can zoom in on the crossing at the top left and make a plot using SURF to get an idea of what's going on:
lambda = linspace(0.85,0.95,100); %# Some new lambda values
betab = linspace(0.95,1,100); %# Some new betab values
[L,B] = meshgrid(lambda,betab); %# Create 2-D grids of values
y = f1(L,B); %# Evaluate f1 at every point in the grid
surf(L,B,y); %# Make a 3-D surface plot of y
axis([0.85 0.95 0.95 1 -5000 5000]); %# Change the axes limits
xlabel('\lambda'); %# Add an x label
ylabel('$\overline{\beta}$','Interpreter','latex'); %# Add a y label
zlabel('y'); %# Add a z label
Notice that there is a lot of high-frequency periodic activity going on along those additional lines, which is why they look so jagged in the contour plot. This is also why a very general utility like EZPLOT was displaying a break in the lines there, since it really isn't designed to handle specific cases of complicated and poorly behaved functions.
EDIT: (response to comments)
These additional lines may not be true zero crossings, although it is difficult to tell from the SURF plot. There may be a discontinuity at those lines, where the function shoots off to -Inf on one side of the line and Inf on the other side of the line. When rendering the surface or computing the contour, these points on either side of the line may be mistakenly connected, giving the false appearance of a zero crossing along the line.
If you want to find a zero crossing given a value of lambda, you can try using the function FZERO along with an anonymous function to turn your function of two variables f1 into a function of one variable fcn:
lambda_zero = 1.5; %# The value of lambda at the zero crossing
fcn = #(x) f1(lambda_zero,x); %# A function of one variable (lambda is fixed)
betab_zero = fzero(fcn,0.94); %# Find the value of betab at the zero crossing,
%# using 0.94 as an initial guess