How to mark co-ordinates of points in Octave using "plot" command? - matlab

I am using the plot command in Octave to plot y versus x values. Is there a way such that the graph also shows the (x,y) value of every coordinate plotted on the graph itself?
I've tried using the help command but I couldn't find any such option.
Also, if it isn't possible, is there a way to do this using any other plotting function?

Have you tried displaying a text box at each coordinate?
Assuming x and y are co-ordinates already stored in MATLAB, you could do something like this:
plot(x, y, 'b.');
for i = 1 : numel(x) %// x and y are the same lengths
text(x(i), y(i), ['(' num2str(x(i)) ',' num2str(y(i)) ')']);
end
The above code will take each point in your graph and place a text box (with no borders) in the format of (x,y) where x and y are the coordinates for all of the points.
Note: You may have to play around with the position of the text boxes, because the above code will place each text box right on top of each pair of co-ordinates. You can play around by adding/subtracting appropriate constants in the first and second parameters of the text function. (i.e. text(x(i) + 1, y(i) - 1, .......); However, if you want something quick and for illustrative purposes, then the above code will be just fine.

Here's a method I've used to do something similar. Generating the strings for the labels is the most awkward part, really (I only had a single number per label, which is a lot simpler)
x = rand(1, 10);
y = rand(1, 10);
scatter(x, y);
% create a text object for each point
t = text(x, y, '');
% generate a cell array of labels - x and y must be row vectors in this case
c = strsplit(sprintf('%.2g,%.2g\n',[x;y]), '\n');
c(end) = []; % the final \n gives us an extra empty cell, remove it
c = c'; % transpose to match the dimensions of t
% assign each label to each text object
set(t, {'String'}, c);
You may want to play around with various properties like 'HorizontalAlignment', 'VerticalAlignment' and 'Margin' to tweak the label positions to your liking.
After a little more thought, here's an alternative, more robust way to generate a suitable cell array of coordinate labels:
c = num2cell([x(:) y(:)], 2);
c = cellfun(#(x) sprintf('%.2g,%.2g',x), c, 'UniformOutput', false);

There is a very useful package labelpoints
in MathWorks File Exchange that does exactly that.
It has a lot of convenient features.

Related

how to plot graphs above each other in matlab [duplicate]

I wanted to generate a plot (X vs Y), and Z values depend on the Y. The example is shown in the figure below. The matrix size of X is same with Z but not Y. I can plot Z against X, but I wanted to combine all the plot into a single plot and become Y against X. I can plot multiple plots into a single plot but the plot is overlapping each other.
My question is there any method I can merge multiple plots into a single plot without overlapping each plot as the difference between each plot is very small (e.g Z1=1,2,3,4,5 and Z2=1.0001,2.0002,3.0001,4.0002,5.0001). So, I wanted to set each Z plot at different Y axis. (e.g Z1 at Y=0, Z2 at Y=2 ...)
Does anyone have any suggestions or idea?
Thank You
I'll clarify the ideas I wrote in a comment.
First, let's get some data:
x = 470:0.1:484;
z1 = cos(x)/2;
z2 = sin(x)/3;
z3 = cos(x+0.2)/2.3;
I'll plot just three data sets, all of this is trivial to extend to any number of data sets.
Idea 1: multiple axes
The idea here is simply to use subplot to create a small-multiple type plot:
ytick = [-0.5,0.0,0.5];
ylim = [-0.9,0.9]);
figure
h1 = subplot(3,1,1);
plot(x,z1);
set(h1,'ylim',ylim,'ytick',ytick);
title('z1')
h2 = subplot(3,1,2);
plot(x,z2);
set(h2,'ylim',ylim,'ytick',ytick);
title('z2')
h3 = subplot(3,1,3);
plot(x,z3);
set(h3,'ylim',ylim,'ytick',ytick);
title('z3')
Note that it is possible to, e.g., remove the tick labels from the top two plot, leaving only labels on the bottom one. You can then also move the axes so that they are closer together (which might be necessary if there are lots of these lines in the same plot):
set(h1,'xticklabel',[],'box','off')
set(h2,'xticklabel',[],'box','off')
set(h3,'box','off')
set(h1,'position',[0.13,0.71,0.8,0.24])
set(h2,'position',[0.13,0.41,0.8,0.24])
set(h3,'position',[0.13,0.11,0.8,0.24])
axes(h1)
title('')
ylabel('z1')
axes(h2)
title('')
ylabel('z2')
axes(h3)
title('')
ylabel('z3')
Idea 2: same axes, plot with offset
This is the simpler approach, as you're dealing only with a single axis. #Zizy Archer already showed how easy it is to shift data if they're all in a single 2D matrix Z. Here I'll just plot z1, z2+2, and z3+4. Adjust the offsets to your liking. Next, I set the 'ytick' property to create the illusion of separate graphs, and set the 'yticklabel' property so that the numbers along the y-axis match the actual data plotted. The end result is similar to the multiple axes plots above, but they're all in a single axes:
figure
plot(x,z1);
hold on
plot(x,z2+2);
plot(x,z3+4);
ytick = [-0.5,0.0,0.5];
set(gca,'ytick',[ytick,ytick+2,ytick+4]);
set(gca,'yticklabel',[ytick,ytick,ytick]);
text(484.5,0,'z1')
text(484.5,2,'z2')
text(484.5,4,'z3')
The simplest would be to shift Z data. But note that Z2 would look like to be oscillating around 1 - so this is a neat visual representation, but might mislead.
% Simple version - shift Z curves by 0, 1, ... (as recommended by #Cris Luengo)
shiftMat = repmat(0 : size(Z, 2)-1, size(Z,1), 1);
Z = Z + shiftMat;
%Min shift up to have non-overlapping - curves touching
for i = 2 : size(Z, 2)
Zdif = (Z(:, i-1) - Z(:, i));
Z(:, i) = Z(:, i) + max(Zdif); % + 0.01 to separate them a little bit.
end
%Bigger shift up, to have all points of Z(2) equal or above all points of z1.
for i = 2 : numZ
Zdif = max(Z(:, i-1))-min(Z(:, i));
Z(:, i) = Z(:, i) + Zdif;
end
Another possibility is to have multiple Y axis and each Z curve plotted against its own Y axis. This is likely fancier and shouldn't mislead, but it is way more work, even after you grab the function, as you still need to position all those axes. MATLAB by default lets you use only 2 axes, so grab a function from fileexchange to add more: https://www.mathworks.com/matlabcentral/fileexchange/9016-addaxis

How to Create Data Markers on a MatLab Plot That Have Lines Extending to X/Y Axis?

I am attempting to create a plot in MatLab of a specified function which has specific data markers that have drop down lines (preferably dashed) to the X/Y axis the correspond to that specific marker.
Below is my MatLab code for just the plot and the markers:
x = 0:4000;
y = 1 - exp(-(power(((x-900)/1015.54),2)));
xmarkers = [1800,2000];
ymarkers = 1 - exp(-(power(((xmarkers-900)/1015.54),2)));
plot(x,y,'b',xmarkers,ymarkers,'b*');
This results in the following plot:
I envision a graph like this, preferably with automatic labels for the specified X/Y value pair at the end of the lines:
My core question would be: Is this possible? And if it is, how would one go about coding this? I understand I could probably manage this manually by adding lines to the plots myself, but this is infeasible for large amounts of markers.
You can define a function which draws the marker:
function draw_marker(x, y)
hold on
plot(x, y, 'b*')
% plot coordinates as text
str = sprintf('(%d, %d)', x, y);
text(x, y, str)
plot([0, x], [y, y], 'k-.')
plot([x, x], [0, y], 'k-.')
end
And then you can create your plot like this:
plot(x,y,'b');
draw_marker(xmarkers(1), ymarkers(1))
draw_marker(xmarkers(2), ymarkers(2))
It would be nicer, of course, if you hand the figure handles as an argument, but the above works.

Plot gradient in matlab and nothing but blank appears

I'm trying to plot the gradient of the real part of a complex function, however what I get is a blank figure. I do not understand what I am doing wrong since the code works with other functions (such as the imaginary part)
% Set up
x = -3:0.2:3;
y1 = (-3:0.2:3);
y = (-3:0.2:3)*1i;
[X, Y]= meshgrid(x,y);
% Complex variable s
s = X + Y;
% Complex function f(z)
z = s + 1./s;
figure
subplot(1,2,1);
[Dx, Dy] = gradient(real(z),.2,.5);
quiver(x,y1,Dx,Dy)
title('u(x,y) gradient, vector field');
%%Imaginary part
subplot(1,2,2)
contour(x,y1,imag(z),linspace(-10,10,100)); title('Contour of Im(f)');
xlabel('x'); ylabel('y'); %clabel(C3);
title('Imaginary part');
Here below is the image I get
I tried to rescale and resize the picture, the domain etc... but couldn't get the gradient to display (the arrows). What am I doing wrong here?
EDIT:
I found out it displays blank perhaps because there are some Inf and -Inf values in the Dy and Dx variables, is there an option to ignore these values or set them to 0?
It looks to me like it works, but the line width of your arrows is too small for you to see.
You can increase it by assigning a handle to the quiver plot like so:
hQuiver = quiver(x,y1,Dx,Dy);
And then, after the plot is created, change any of its many properties like so:
set(hQuiver,'LineWidth',4)
or do it all in the call to quiver:
hQuiver = quiver(x,y1,Dx,Dy,'LineWidth',4);
In this case it gives the following:
EDIT:
To answer your secondary question, you can set elements that are equal to +Inf or -Inf to any value you want using isinf:
Dx(isinf(Dx)) = 0;
and
Dy(isinf(Dy)) = 0;
It is not blank. You've plotted the quiver diagram (usually used in optical flow diagrams). It is giving an inward pointing arrow at each of the locations formed by the grid with points in x and y1.

Plot a cell into a time-changing curve

I have got a cell, which is like this : Data={[2,3],[5,6],[1,4],[6,7]...}
The number in every square brackets represent x and y of a point respectively. There will be a new coordinate into the cell in every loop of my algorithm.
I want to plot these points into a time-changing curve, which will tell me the trajectory of the point.
As a beginner of MATLAB, I have no idea of this stage. Thanks for your help.
Here is some sample code to get you started. It uses some basic Matlab functionalities that you will hopefully find useful as you continue using it. I added come data points to you cell array for illustrative purposes.
The syntax to access elements into the cell array might seem weird but is important. Look here for details about cell array indexing.
In order to give nice colors to the points, I generated an array based on the jet colormap built-in in Matlab. Basically issuing the command
Colors = jet(N)
create a N x 3 matrix in which every row is a 3-element color ranging from blue to red. That way you can see which points were detected before other (i.e. blue before red). Of course you can change that to anything you want (look here if you're interested).
So here is the code. If something is unclear please ask for clarifications.
clear
clc
%// Get data
Data = {[2,3],[5,6],[1,4],[6,7],[8,1],[5,2],[7,7]};
%// Set up a matrix to color the points. Here I used a jet colormap
%// available from MATLAB but that could be anything.
Colors = jet(numel(Data));
figure;
%// Use "hold all" to prevent the content of the figure to be overwritten
%// at every iterations.
hold all
for k = 1:numel(Data)
%// Note the syntax used to access the content of the cell array.
scatter(Data{k}(1),Data{k}(2),60,Colors(k,:),'filled');
%// Trace a line to link consecutive points
if k > 1
line([Data{k-1}(1) Data{k}(1)],[Data{k-1}(2) Data{k}(2)],'LineStyle','--','Color','k');
end
end
%// Set up axis limits
axis([0 10 0 11])
%// Add labels to axis and add a title.
xlabel('X coordinates','FontSize',16)
ylabel('Y coordinates','FontSize',16)
title('This is a very boring title','FontSize',18)
Which outputs the following:
This would be easier to achieve if all of your data was stored in a n by 2 (or 2 by n) matrix. In this case, each row would be a new entry. For example:
Data=[2,3;
5,6;
1,4;
6,7];
plot(Data(:, 1), Data(:, 2))
Would plot your points. Fortunately, Matlab is able to handle matrices which grow on every iteration, though it is not recommended.
If you really wanted to work with cells, there are a couple of ways you could do it. Firstly, you could assign the elements to a matrix and repeat the above method:
NumPoints = numel(Data);
DataMat = zeros(NumPoints, 2);
for I = 1:NumPoints % Data is a cell here
DataMat(I, :) = cell2mat(Data(I));
end
You could alternatively plot the elements straight from the cell, though this would limit your plot options.
NumPoints = numel(Data);
hold on
for I = 1:NumPoints
point = cell2mat(Data(I));
plot(point(1), point(2))
end
hold off
With regards to your time changing curve, if you find that Matlab starts to slow down after it stores lots of points, it is possible to limit your viewing window in time with clever indexing. For example:
index = 1;
SamplingRate = 10; % How many times per second are we taking a sample (Hertz)?
WindowTime = 10; % How far into the past do we want to store points (seconds)?
NumPoints = SamplingRate * WindowTime
Data = zeros(NumPoints, 2);
while running
% Your code goes here
Data(index, :) = NewData;
index = index + 1;
index = mod(index-1, NumPoints)+1;
plot(Data(:, 1), Data(:, 2))
drawnow
end
Will store your data in a Matrix of fixed size, meaning Matlab won't slow down.

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