How to label line in Matlab plot - matlab

I wrote a code plot 17 lines in the same graph. I want to label all line on the graph . Can u help me ?
clear all
close all
clc
syms w
wn=4000 %rad/s
k=1
for n=0:0.05:0.8
w=0:10:1884;
H=1./sqrt((1-(w/wn).^2)+(2*n*w/wn).^2);
x=w/wn
plot(x,H)
title('Time versus Response Graph of n');
xlabel('Time(s)');
ylabel('Response(m)');
k=k+1
hold on
end
I want to clariy which value is equal to which line.

That's usually done by annotation, and I think it is done manually. Since you have a lot of graphs and not much space, I suggest you use text to add the label at the end of the line. So in the loop add (under ylabel for example)
str = sprintf(' n = %.2f',n);
text(x(end),H(end),str);
This will result in
As you can see there is an overlap in the beginning because the curves are close to each other. You can hardcode a little offset for the first one as follows: (Annotation is graph dependent so I think it's ok to hardcode this)
if n == 0
text(x(end),H(end)+.005,str);
else
text(x(end),H(end),str);
end
Result:
General remarks on your code:
you don't use w symbolic so delete syms w
you don't use k so get rid of it as well
w and x can be moved outside the loop and w/wn can be replaced by x
You can also write this without a loop:
wn=4000; %rad/s
w=0:10:1884;
x=w/wn;
n=0:0.05:0.8;
N = length(n);
H=1./sqrt((1-(ones(N,1)*x).^2)+(2*n.'*x).^2);
plot(x,H)
title('Time versus Response Graph of n');
xlabel('Time(s)');
ylabel('Response(m)');
str = sprintf(' n = %.2f\t',n);
strs = strsplit(str,'\t');
offset = zeros(N,1);
offset(1)=.005;
offset(2)=.001;
text(x(end).*ones(N,1),H(:,end)+offset,strs(1:N));
This way it is easier to adjust the offsets of the different curves. (Note I've added an offset for the second curve as well leading to graph below)
`

Related

how to use subplot within two loops

I need one figure with multiple graphs within two loops.
for i=1:length(state)
[block]
for j=1:length(channel)
[block]
subplot(length(state),length(channel)),j)
plot(a,b)% a and b are arrays of doubles.
end
end
I want one figure with size =length(state)*length(channel); for instance I need all the graphs of state(1)within all channels in the first row etc...
But what I get is multiple figures (the length of state).
If I understand well enough here is a way to do it :
figure()
lx = 2;
ly = 3;
for ii = 1:lx
for jj = 1:ly
subplot(lx,ly,ly*(ii-1)+jj)
plot(ii,jj,'o')
end
end
Why ly*(ii-1)+jj?
The syntax of subplot is the following : subplot(nbRows,nbCols,position) and the position is given by an unique index going over all available subplots (see image) which is ly*(ii-1)+jj.

How do I adjust this code so that I can enter how many runs I want and it will store each run in a matrix?

I have created this code to generate a 1 set of lottery numbers, but I am trying to make it so that the user can enter how many sets they want (input n), and it will print out as one long matrix of size nX6? I was messing around with a few options from online suggestions, but to no avail. I put the initial for i=1:1:n at the beginning, but I do not know how to store each run into a growing matrix. Right now it still generates just 1 set.
function lottery(n)
for i=1:1:n
xlow=1;
xhigh=69;
m=5;
i=1;
while (i<=m)
lottonum(i)=floor(xlow+rand*(xhigh-xlow+1));
flag=0;
for j=1:i-1
if (lottonum(i)==lottonum(j))
flag=1;
end
end
if flag==0
i=i+1;
end
end
ylow=1;
yhigh=26;
m=1;
lottonum1=floor(ylow+rand*(yhigh-ylow+1));
z = horzcat(lottonum, lottonum1);
end
disp('The lotto numbers picked are')
fprintf('%g ',z)
disp (' ')
The problem is that you are not storing or displaying the newly generated numbers, only the last set. To solve this, initialize z with NaNs or zeros, and later index z to store each set in a row of z, by using z(i,:) = lottonum.
However, you are using i as iterator in the while loop already, so you should use another variable, e.g. k.
You can also set z as an output of the function, so you can use this matrix in some other part of a program.
function z = lottery(n)
% init z
z = NaN(n,6);
for k = 1:n
xlow=1;
xhigh=69;
m=5;
i=1;
while (i<=m)
lottonum(i)=floor(xlow+rand*(xhigh-xlow+1));
flag=0;
for j=1:i-1
if (lottonum(i)==lottonum(j))
flag=1;
end
end
if flag==0
i=i+1;
end
end
ylow=1;
yhigh=26;
lottonum1 = floor(ylow+rand*(yhigh-ylow+1));
z(k,:) = horzcat(lottonum, lottonum1); % put the numbers in a row of z
end
disp('The lotto numbers picked are')
disp(z) % prettier display than fprintf in this case.
disp (' ')
end
The nice answer from rinkert corrected your basic mistakes (like trying to modify your loop iterator i from within the loop => does not work), and answered your question on how to store all your results.
This left you with a working code, however, I'd like to propose to you a different way to look at it.
The porposed architecture is to divide the tasks into separate functions:
One function draw_numbers which can draw N numbers randomly (and does only that)
One function draw_lottery which call the previous function as many times as it needs (your n), collect the results and display them.
draw_lottery
This architecture has the benefit to greatly simplify your main function. It can now be as simple as:
function Draws = draw_lottery(n)
% define your draw parameters
xmin = 1 ; % minimum number drawn
xmax = 69 ; % maximum number drawn
nballs = 5 ; % number of number to draw
% pre allocate results
Draws = zeros( n , nballs) ;
for iDraw=1:1:n
% draw "nballs" numbers
thisDraw = draw_numbers(xmin,xmax,nballs) ;
% add them to the result matrix
Draws(iDraw,:) = thisDraw ;
end
disp('The lotto numbers picked are:')
disp (Draws)
disp (' ')
end
draw_numbers
Instead of using a intricated set of if conditions and several iterators (i/m/k) to branch the program flow, I made the function recursive. It means the function may have to call itself a number of time until a condition is satisfied. In our case the condition is to have a set of nballs unique numbers.
The function:
(1) draws N integer numbers randomly, using randi.
(2) remove duplicate numbers (if any). Using unique.
(3) count how many unique numbers are left Nu
(4a) if Nu = N => exit function
(4b) if Nu < N => Call itself again, sending the existing Nu numbers and asking to draw an additional N-Nu numbers to add to the collection. Then back to step (2).
in code, it looks like that:
function draw = draw_numbers(xmin,xmax,nballs,drawn_set)
% check if we received a partial set
if nargin == 4
% if yes, adjust the number of balls to draw
n2draw = nballs - numel(drawn_set) ;
else
% if not, make a full draw
drawn_set = [] ;
n2draw = nballs ;
end
% draw "nballs" numbers between "xmin" and "xmax"
% and concatenate these new numbers with the partial set
d = [drawn_set , randi([xmin xmax],1,n2draw)] ;
% Remove duplicate
drawn_set = unique(d) ;
% check if we have some more balls to draw
if numel(drawn_set) < nballs
% draw some more balls
draw = draw_numbers(xmin,xmax,nballs,drawn_set) ;
else
% we're good to go, assign output and exit funtion
draw = drawn_set ;
end
end
You can have both functions into the same file if you want.
I encourage you to look at the documentation of a couple of Matlab built-in functions used:
randi
unique

Title over a group of subplots

I want a figure with six plots inside; I split it with subplots. For example
for i = 1:12
subplot(3,4,i)
plot(peaks)
title(['Title plot ',num2str(i)])
end
I would like to add two global titles, let's say a global title for the six plots on the left hand side and another title for the six other plots on the right hand side.
I don't have 2018b version, so I cannot use sgtitle('Subplot Title');. Is it possible use suptitle('my title'); somehow?
I can use text() but resizing the window, the two labels move.
You can use annotation for that, with the location of subplots 1 and 3:
for k = 1:12
sp(k) = subplot(3,4,k);
plot(peaks)
title(['Title plot ',num2str(k)])
end
spPos = cat(1,sp([1 3]).Position);
titleSettings = {'HorizontalAlignment','center','EdgeColor','none','FontSize',18};
annotation('textbox','Position',[spPos(1,1:2) 0.3 0.3],'String','Left title',titleSettings{:})
annotation('textbox','Position',[spPos(2,1:2) 0.3 0.3],'String','Right title',titleSettings{:})
I did not test this, but you can get the handle to a subplot object and then perform the title method on this handle. I would also suggest to then apply the title after the loop.
CODE
for k = 1:12
h(k) = subplot(3, 4, i)
plot(peak)
end
title(h(1), 'Left side')
title(h(8), 'Right side') % find out the right index yourself
Remark:
Do not use i or j as iteration variable for they are already defined in the namespace of MATLAB as imaginary unit.

How to label graph edges with a loop?

I'm using a for loop to add more nodes and edges on my plot. However, when I add labels on new edges the old labels are removed. I don't know how to keep old edge-labels nor how to store the results of labeledge.
This is what I have got so far.
for r = 1: 10
for j = 1:10
H = addnode(P,nodeName{r}{j});
P = addedge(H, s{r}{j}, t{r}{j}, w{r}{j});
figure;
hold on;
h = plot(P);
labeledge(h,s{r}{j},t{r}{j},labelText{r}{j})
end
end
Every time in the new plot, I can only see the newest cluster of labels while old labels are gone. Ideally, I'd love to hold on the results of labeledge but hold on can't do this. I need to show labels in each step in the loop, thus adding another overall labeledge is not my ideal solution. Any hint would be appreciated.
Edit: All my variables are multiple cells of difference sizes in cell arrays. I use for loop to help to pick up vectors from cells because I don't know how to insert all the levels of information from such cell arrays of cells etc. into addNode function.
The main problem in your code is that you keep plotting the graph again and again. This isn't necessary. Instead, use one loop to create the graph object (G), then plot it all at once, and then use another loop for labeling the graph:
P = graph;
for r = 1: 10
for j = 1:10
P = addedge(P, s{r}{j}, t{r}{j}, w{r}{j});
end
end
h = plot(P);
for r = 1: 10
for j = 1:10
labeledge(h,s{r}{j},t{r}{j},labelText{r}{j})
end
end
If you wish to plot your graph on every iteration, you can use subgraph for that:
for k = 1:height(P.Nodes)
H = subgraph(P,1:k);
figure;
h = plot(H);
c = 1;
out = false;
for r = 1: 10
if ~out
for j = 1:10
if c < k
labeledge(h,c,labelText{r}{j})
else
out = true;
break
end
c = c+1;
end
else
break
end
end
end
Besides that, you should know that (from Matlab documentation):
For the best performance, construct graphs all at once using a single call to graph. Adding nodes or edges in a loop can be slow for large graphs.
Also, regardless of the above recommendation, for an easier manipulation of your data, you should first convert your cells to an array. If your cell array contains a different number of elements in each cell, then it is better to collapse it all to one column:
C = [s{:}]; % and the same for t and w
while any(cellfun(#iscell,C))
C = vertcat(C{:});
end
C = cellfun(#(x) x(:),C,'UniformOutput', false);
S = vertcat(C{:});
Labels = [labelText{:}]; % and the same nodeName
while any(cellfun(#iscell,Labels))
Labels = vertcat(Labels{:});
end
Try to remove the 'figure;' command out of the FOR loop and try to see if this worked.

MATLAB - Labeling Curves During Iteration

I want to show the p value that was used to generate each curve next to each of the curves plotted. Note that since there is a plot of E and -E, the same p value should be next to both. I've been attempting this for a while and I have not come across anything super useful.
t = -3.1;%coupling
a = 1;%distance between r1 and r3
n = 5;%latice vector span in a1 direction
m = 1;%latice vector span in a2 direction
i = -7;%unique axial vector t_hat direction
j = 11;%unique axial vector c_hat direction
max_p = abs((n*(i+j/2)-j*(m+n/2)));%# of unique p values
La = sqrt(3)*sqrt(m^2+n*m+n^2)*a/gcd(2*n+m,2*m+n);%unit cell length
C = sqrt(n^2+n*m+m^2);%circumference of the nanotube
hold on;
for p=0:1:max_p
kt = -pi/La:.05:pi/La;
kc = 2*pi*p/C;
ka1 = kc*a*.5*(2*n+m)/C + kt*a*sqrt(3)*.5*m/C;
ka2 = kc*a*.5*(n+2*m)/C - kt*a*sqrt(3)*.5*n/C;
E = abs(t+t*exp(1i*ka2)+t*exp(1i*ka1));
title_ = sprintf('(%d,%d) Carbon Nanotube Dispersion Diagram',n,m);
title(title_);
xlabel('k_{t}a');
ylabel('Energy (eV)');
plot(kt,E);
plot(kt,-E);
end
There is a command named text that writes comments into the figures,
http://www.mathworks.se/help/techdoc/ref/text.html
with if you can't solve it with that and the to string operation i misunderstood the question
First, do you need to plot both E and -E? Since these are the same except for their sign you don't really add any information to the plot by having -E there as well. However, if you do need both lines, then just construct an array of strings for the legend, during the loop, which has each string included twice (once for E and once for -E).
... Initial calculations ...
hold on;
for p=0:1:max_p
kt = -pi/La:.05:pi/La;
kc = 2*pi*p/C;
ka1 = kc*a*.5*(2*n+m)/C + kt*a*sqrt(3)*.5*m/C;
ka2 = kc*a*.5*(n+2*m)/C - kt*a*sqrt(3)*.5*n/C;
E = abs(t+t*exp(1i*ka2)+t*exp(1i*ka1));
plot(kt,E);
plot(kt,-E);
% Construct array containing legend text
legend_text{2*(p+1)-1} = strcat('p=', num2str(p));
legend_text{2*(p+1)} = strcat('p=', num2str(p));
end
title_ = sprintf('(%d,%d) Carbon Nanotube Dispersion Diagram',n,m);
title(title_);
xlabel('k_{t}a');
ylabel('Energy (eV)');
legend(legend_text)
I am sure there is a more elegant way of constructing the legend text, but the above code works. Also, notice that I moved the calls to xlabel, ylabel and title to outside of the loop. This way they are only called once and not for each iteration of the loop.
Finally, you need to take care to ensure that each iteration of the loop plots with a different line colour or line style (see edit below). You could colour/style each pair of E and -E lines the same for a given iteration of the loop and just display the legend for E (or -E), which would obviously halve the number of legend entries. To do this you will need to hide one of line's handle visibility - this prevents it from getting an item in the legend. To do this use the following in your loop:
plot(kt, E);
plot(kt,-E, 'HandleVisibility', 'off');
% Construct array containing legend text
legend_text{p+1} = strcat('p=', num2str(p));
Finally, it is best to include clear all at the top of your Matlab scripts.
Edit: To have each plotted line use a different colour for each iteration of your loop use something like the following
... initial calculations ...
cmap = hsv(max_p); % Create a max_p-by-3 set of colors from the HSV colormap
hold on;
for p = 0:1:max_p
plot(kt, E, 'Color', cmap(p,:)); % Plot each pair of lines with a different color
plot(kt, -E, 'Color', cmap(p,:));
end