2D plot (add some lines) - matlab

I want to make a straight line at 4 as the paper and i want to find the values of a and b for which the max value is greater than 4.
My code
objfun file
function f = threestate2(x,a,b)
c1 =cos(x(1))*(cos(x(5))*(cos(x(9))+cos(x(11)))+cos(x(7))*(cos(x(9))-cos(x(11))))+ ...
cos(x(3))*(cos(x(5))*(cos(x(9))-cos(x(11)))-cos(x(7))*(cos(x(9))+cos(x(11))));
c2=sin(x(1))*(sin(x(5))*(sin(x(9))*cos(x(2)+x(6)+x(10))+sin(x(11))*cos(x(2)+x(6)+x(12))) ...
+sin(x(7))*(sin(x(9))*cos(x(2)+x(8)+x(10))-sin(x(11))*cos(x(2)+x(8)+x(12))))+ ...
sin(x(3))*(sin(x(5))*(sin(x(9))*cos(x(4)+x(6)+x(10))-sin(x(11))*cos(x(4)+x(6)+x(12))) ...
-sin(x(7))*(sin(x(9))*cos(x(4)+x(8)+x(10))+sin(x(11))*cos(x(4)+x(8)+x(12))));
A1=a^2-b^2;
A2=2*a*b;
f1=A1*c1 +A2*c2;
f=-(f1^2);
my main file
clear
close
clc
%x=[x(1),x(2),x(3),x(4),x(5),x(6),x(7),x(8),x(9),x(10),x(11),x(12)]; % angles;
lb=[0,0,0,0,0,0,0,0,0,0,0,0];
ub=[pi,2*pi,pi,2*pi,pi,2*pi,pi,2*pi,pi,2*pi,pi,2*pi];
options = optimoptions(#fmincon,'TolX',10^-12,'MaxIter',1500,'MaxFunEvals',10^8,'Algorithm','sqp','TolFun',10^-8);
a=0:0.01:1;
w=NaN(size(a));
ww=NaN(size(a));
for k=1:30
x0=rand([1,12]).*ub*.9986;%7976
for i=1:length(a)
bhelp=1-a(i)^2;
if (bhelp>0 || bhelp==0)
b=sqrt(bhelp);
[~,fval]=fmincon(#(x)threestate2(x,a(i),b),x0,[],[],[],[],lb,ub,[],options);
w(i)=sqrt(-fval);
else
w(i)=nan;
end
ww=max(w,ww);
end
x=a.^2;
end
plot(x,ww)
grid on
ylabel('\fontname{Times New Roman} S_{max}(\Psi_{gs})')
xlabel('\fontname{Times New Roman}\alpha^2')
The plot i got is2d plot
So i want it like this picthis how it should look like

Related

How to force MATLAB function area to hold on in figure

I'm working on this function which gets axis handler and data, and is supposed to plot it correctly in the axis. The function is called in for loop. It's supposed to draw the multiple data in one figure. My resulted figure is shown below.
There are only two correctly plotted graphs (those with four colors). Others miss areas plotted before the final area (red area is the last plotted area in each graph). But the script is same for every axis. So where can be the mistake? The whole function is written below.
function [] = powerSpectrumSmooth(axis,signal,fs)
N= length(signal);
samplesPer1Hz = N/fs;
delta = int16(3.5*samplesPer1Hz); %last sample of delta frequncies
theta = int16(7.5*samplesPer1Hz); %last sample of theta frequncies
alpha = int16(13*samplesPer1Hz); %last sample of alpha frequncies
beta = int16(30*samplesPer1Hz); %last sample of beta frequncies
x=fft(double(signal));
powerSpectrum = 20*log10(abs(real(x)));
smoothPS=smooth(powerSpectrum,51);
PSmin=min(powerSpectrum(1:beta));
y1=[(smoothPS(1:delta)); zeros(beta-delta,1)+PSmin];
y2=[zeros(delta-1,1)+PSmin; (smoothPS(delta:theta)); zeros(beta-theta,1)+PSmin];
y3=[zeros(theta-1,1)+PSmin; (smoothPS(theta:alpha)); zeros(beta-alpha,1)+PSmin];
y4=[zeros(alpha-1,1)+PSmin; (smoothPS(alpha:beta))];
a1=area(axis,1:beta,y1);
set(a1,'FaceColor','yellow')
hold on
a2=area(axis,1:beta,y2);
set(a2,'FaceColor','blue')
a3=area(axis,1:beta,y3);
set(a3,'FaceColor','green')
a4=area(axis,1:beta,y4);
set(a4,'FaceColor','red')
ADDED
And here is the function which calls the function above.
function [] = drawPowerSpectrum(axesContainer,dataContainer,fs)
size = length(axesContainer);
for l=1:size
powerSpectrumSmooth(axesContainer{l},dataContainer{l},fs)
set(axesContainer{l},'XTickLabel','')
set(axesContainer{l},'YTickLabel','')
uistack(axesContainer{l}, 'top');
end
ADDED 29th July
Here is a script which reproduces the error, so you can run it in your computer. Before running it again you might need to clear variables.
len = 9;
axesContainer = cell(len,1);
x = [0.1,0.4,0.7,0.1,0.4,0.7,0.1,0.4,0.7];
y = [0.1,0.1,0.1,0.4,0.4,0.4,0.7,0.7,0.7];
figure(1)
for i=1:len
axesContainer{i} = axes('Position',[x(i),y(i),0.2,0.2]);
end
dataContainer = cell(len,1);
N = 1500;
for i=1:len
dataContainer{i} = rand(1,N)*100;
end
for l=1:len
y1=[(dataContainer{l}(1:N/4)) zeros(1,3*N/4)];
y2=[zeros(1,N/4) (dataContainer{l}(N/4+1:(2*N/4))) zeros(1,2*N/4)];
y3=[zeros(1,2*N/4) (dataContainer{l}(2*N/4+1:3*N/4)) zeros(1,N/4)];
y4=[zeros(1,3*N/4) (dataContainer{l}(3*N/4+1:N))];
axes=axesContainer{l};
a1=area(axes,1:N,y1);
set(a1,'FaceColor','yellow')
hold on
a2=area(axes,1:N,y2);
set(a2,'FaceColor','blue')
hold on
a3=area(axes,1:N,y3);
set(a3,'FaceColor','green')
hold on
a4=area(axes,1:N,y4);
set(a4,'FaceColor','red')
set(axes,'XTickLabel','')
set(axes,'YTickLabel','')
end
My result of this script is plotted below:
Again only one picture contains all areas.
It looks like that every call to plot(axes,data) deletes whatever was written in axes.
Important note: Do not use a variable name the same as a function. Do not call something sin ,plot or axes!! I changed it to axs.
To solve the problem I just used the classic subplot instead of creating the axes as you did:
len = 9;
axesContainer = cell(len,1);
x = [0.1,0.4,0.7,0.1,0.4,0.7,0.1,0.4,0.7];
y = [0.1,0.1,0.1,0.4,0.4,0.4,0.7,0.7,0.7];
figure(1)
dataContainer = cell(len,1);
N = 1500;
for i=1:len
dataContainer{i} = rand(1,N)*100;
end
for l=1:len
y1=[(dataContainer{l}(1:N/4)) zeros(1,3*N/4)];
y2=[zeros(1,N/4) (dataContainer{l}(N/4+1:(2*N/4))) zeros(1,2*N/4)];
y3=[zeros(1,2*N/4) (dataContainer{l}(2*N/4+1:3*N/4)) zeros(1,N/4)];
y4=[zeros(1,3*N/4) (dataContainer{l}(3*N/4+1:N))];
axs=subplot(3,3,l);
a1=area(axs,1:N,y1);
set(a1,'FaceColor','yellow')
hold on
a2=area(axs,1:N,y2);
set(a2,'FaceColor','blue')
hold on
a3=area(axs,1:N,y3);
set(a3,'FaceColor','green')
hold on
a4=area(axs,1:N,y4);
set(a4,'FaceColor','red')
set(axs,'XTickLabel','')
set(axs,'YTickLabel','')
axis tight % this is to beautify it.
end
As far as I know, you can still save the axs variable in an axescontainer and then modify the properties you want (like location).
I found out how to do what I needed.
len = 8;
axesContainer = cell(len,1);
x = [0.1,0.4,0.7,0.1,0.4,0.7,0.1,0.4];
y = [0.1,0.1,0.1,0.4,0.4,0.4,0.7,0.7];
figure(1)
for i=1:len
axesContainer{i} = axes('Position',[x(i),y(i),0.2,0.2]);
end
dataContainer = cell(len,1);
N = 1500;
for i=1:len
dataContainer{i} = rand(1,N)*100;
end
for l=1:len
y1=[(dataContainer{l}(1:N/4)) zeros(1,3*N/4)];
y2=[zeros(1,N/4) (dataContainer{l}(N/4+1:(2*N/4))) zeros(1,2*N/4)];
y3=[zeros(1,2*N/4) (dataContainer{l}(2*N/4+1:3*N/4)) zeros(1,N/4)];
y4=[zeros(1,3*N/4) (dataContainer{l}(3*N/4+1:N))];
axes=axesContainer{l};
Y=[y1',y2',y3',y4'];
a=area(axes,Y);
set(axes,'XTickLabel','')
set(axes,'YTickLabel','')
end
The area is supposed to work with matrices like this. The tricky part is, that the signal in every next column is not plotted absolutely, but relatively to the data in previous column. That means, if at time 1 the data in first column has value 1 and data in second column has value 4, the second column data is ploted at value 5. Source: http://www.mathworks.com/help/matlab/ref/area.html

plotting a graph by calling a function

M = round(csvread('noob.csv'))
save projectDAT.dat M -ascii
load projectDAT.dat
mat = (projectDAT)
sum_of_rows(mat)
plotthegraph
This is my main script. I have a excel file, which opens up a 20 x 20 matrix in matlab. Now I have to call a function in this mainscript, which would find the sum of elements in a row for me and put them in a column vector. Here is my function:
function sumRow = sum_of_rows(mat)
[m n] = size(mat);
sumRow = zeros(m,1);
for i = 1:m;
for j = 1:n;
sumRow(i) = sumRow(i) + mat(i,j);
end
end
vec = sumRow;
end
I am required to plot a line graph using this column vector. I am supposed to call a function from the mainscript. The function should be able to take the input from this sum_of_rows function. I tried doing this:
function plotthegraph(~)
% Application for plotting the height of students
choice = menu('Choose the type of graph', 'Plot the data using a line plot', 'Plot the data using a bar plot');
if choice == 1
plot_line(sum_of_rows)
y = sum_of_rows
x = 1:length(y)
plot(x,y)
title('Bar graph')
xlabel('Number of characters')
ylabel('Number of grades')
elseif choice == 2
plot_bar(sum_of_columns)
end
Its not working out though. Can someone please help me out, I would really appreciate it. Thank you.
You could do the following to get rid of the sum_of_rows function:
sumRow = sum(mat,2);
The second argument tells the sum to add all the columns in the matrix rowwise, giving you the sum of each row in mat.
To plot this vector you need to pass it as input to your function. Also matlab takes care of the x values for you if you do not specify variable along, doing exactly what you did manually while defining x. Your function would look like this:
function plotthegraph(sum_of_rows)
% Application for plotting the height of students
prompt='Type 1 for line plot, 2 for bar';
choice=input(prompt)
if choice == 1
plot(sum_of_rows)
title('Line graph')
xlabel('Number of characters')
ylabel('Number of grades')
elseif choice == 2
bar(sum_of_rows)
end
end
So you'd have to call this function passing the sum of rows:
plotthegraph(sumRow)

plotting trajectories using matlab

Im trying to plot trajectories on matlab
My data file (try.txt) that has the trajectories looks like this:
NumofTrajectories
TrajID1 #ofPoints x y x y....
TrajID2 #ofPoints x y x y....
example:
7
0 23 898.6 673.0 859.1 669.9 813.7 667.8 776.8 664.0 739.8 662.1 699.9 654.7 664.5 649.6 625.3 645.5 588.2 640.6 552.3 634.2 516.6 628.2 477.2 624.3 442.1 613.6 406.7 603.4 369.5 599.8 332.7 594.1 297.4 585.2 258.6 583.7 224.1 573.1 191.2 556.8 152.7 554.0 115.1 546.0 79.6 535.8
1 8 481.4 624.9 445.9 596.3 374.5 573.9 354.2 541.0 334.2 508.9 327.6 474.1 324.6 437.5 324.2 390.3
2 24 151.6 570.8 188.3 556.5 225.1 547.7 257.9 529.4 292.9 509.8 326.8 496.8 356.2 476.0 391.2 463.3 423.7 447.9 455.7 431.8 489.2 416.0 524.3 405.3 560.0 395.9 595.8 385.6 632.8 376.1 671.5 372.0 706.9 361.8 742.3 347.3 778.0 334.5 820.5 336.5 856.5 325.0 894.5 309.5 946.1 309.9 990.5 287.0
3 3 594.2 580.4 566.6 544.3 544.9 509.4
4 5 281.8 661.9 266.8 623.4 246.2 576.4 229.7 541.0 220.9 498.4
5 2 563.6 511.3 532.5 479.7
6 5 571.9 617.7 525.6 576.4 481.0 551.9 456.8 524.2 419.7 474.0
I'm trying to plot this on matlab
my code is as follows:
clc;
clear;
%read the input
importfile('try.txt')
%See how many trajectorys there are convert to number
nTraj=str2num(cell2mat(textdata));
%loop over the trajectories
for i = 1:nTraj
disp(data(i,1));
%print the current trajectory number of points
disp(data(i,2));
%get the x-y coordinates of each trajectory
current_traj=data(i,2);
for j=1:current_traj
points=data(i,3:j*2+2);
end
%print the x-y coordinates of each trajectory
%disp(points);
%seperate the x-y coordinates of each trajectory
x=points(1:2:length(points)-1)
y=points(2:2:length(points))
xlabel('latitude');
ylabel('longitude');
plot(x,y,'r');
grid on ;
hold on;
end
And function importfile:
function importfile(fileToRead1)
%IMPORTFILE(FILETOREAD1)
% Imports data from the specified file
% FILETOREAD1: file to read
DELIMITER = ' ';
HEADERLINES = 1;
% Import the file
newData1 = importdata(fileToRead1, DELIMITER, HEADERLINES);
% Create new variables in the base workspace from those fields.
vars = fieldnames(newData1);
for i = 1:length(vars)
assignin('base', vars{i}, newData1.(vars{i}));
end
The code sometimes works and usually gives me an error say:
Index exceeds matrix dimensions.
Error in ==> plotTrajectory at 23
points=data(i,3:j*2+2);
Can someone explain the error and tell me how to fix it?
The trajectories in try.txt have different lengths. importdata will use the first line to determine the length of your data. If another line is the longest, this line will be split over several lines of your imported matrix. At least this is what debugging shows. I would suggest you use another method to read your file. For me dlmread works:
%read the input
data = dlmread('try.txt', ' ');
% remove header
data = data(2:end,:);
%See how many trajectorys there are convert to number
nTraj=size(data,1);
You can replace your first lines with this code and remove your importfilefunction.

Rolling window for averaging using MATLAB

I have the following code, pasted below. I would like to change it to only average the 10 most recently filtered images and not the entire group of filtered images. The line I think I need to change is: Yout(k,p,q) = (Yout(k,p,q) + (y.^2))/2;, but how do I do it?
j=1;
K = 1:3600;
window = zeros(1,10);
Yout = zeros(10,column,row);
figure;
y = 0; %# Preallocate memory for output
%Load one image
for i = 1:length(K)
disp(i)
str = int2str(i);
str1 = strcat(str,'.mat');
load(str1);
D{i}(:,:) = A(:,:);
%Go through the columns and rows
for p = 1:column
for q = 1:row
if(mean2(D{i}(p,q))==0)
x = 0;
else
if(i == 1)
meanvalue = mean2(D{i}(p,q));
end
%Calculate the temporal mean value based on previous ones.
meanvalue = (meanvalue+D{i}(p,q))/2;
x = double(D{i}(p,q)/meanvalue);
end
%Filtering for 10 bands, based on the previous state
for k = 1:10
[y, ZState{k}] = filter(bCoeff{k},aCoeff{k},x,ZState{k});
Yout(k,p,q) = (Yout(k,p,q) + (y.^2))/2;
end
end
end
% for k = 2:10
% subplot(5,2,k)
% subimage(Yout(k)*5000, [0 100]);
% colormap jet
% end
% pause(0.01);
end
disp('Done Loading...')
The best way to do this (in my opinion) would be to use a circular-buffer to store your images. In a circular-, or ring-buffer, the oldest data element in the array is overwritten by the newest element pushed in to the array. The basics of making such a structure are described in the short Mathworks video Implementing a simple circular buffer.
For each iteration of you main loop that deals with a single image, just load a new image into the circular-buffer and then use MATLAB's built in mean function to take the average efficiently.
If you need to apply a window function to the data, then make a temporary copy of the frames multiplied by the window function and take the average of the copy at each iteration of the loop.
The line
Yout(k,p,q) = (Yout(k,p,q) + (y.^2))/2;
calculates a kind of Moving Average for each of the 10 bands over all your images.
This line calculates a moving average of meanvalue over your images:
meanvalue=(meanvalue+D{i}(p,q))/2;
For both you will want to add a buffer structure that keeps only the last 10 images.
To simplify it, you can also just keep all in memory. Here is an example for Yout:
Change this line: (Add one dimension)
Yout = zeros(3600,10,column,row);
And change this:
for q = 1:row
[...]
%filtering for 10 bands, based on the previous state
for k = 1:10
[y, ZState{k}] = filter(bCoeff{k},aCoeff{k},x,ZState{k});
Yout(i,k,p,q) = y.^2;
end
YoutAvg = zeros(10,column,row);
start = max(0, i-10+1);
for avgImg = start:i
YoutAvg(k,p,q) = (YoutAvg(k,p,q) + Yout(avgImg,k,p,q))/2;
end
end
Then to display use
subimage(Yout(k)*5000, [0 100]);
You would do sth. similar for meanvalue

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