MATLAB: adding contour lines to points [duplicate] - matlab

I'd like to know how to draw a graph with 2 electric charges Q and -Q and their total E, for a specific point (eg (4,5)), with contour f..
My M-file actually scans the area (from -3x to 3x) and calculates E for every spot, stores it in a table, but after this, I don't know how to use contourf to draw it..
syms i
syms j
syms d
d=input('dwse thn timi tou d,ths apostashs')
j=0
i=0
for j=-d:d/1000:d
j=j+1
for i=-d:d/1000:d
i=i+1
z=(i,j)
end, end

Based on Coulomb's law, the electric field created by a single, discrete charge q at a distance r is given by:
E=q/(4*pi*e0*r.^2);
If you have several charges you can use the superposition principle and add the contribution of each charge.
The only thing left to do is to create a grid to compute the electrical field. For this you can use tha Matlab function meshgrid.
A simple example in Matlab would be:
k=1/4/pi/8.854e-12;
d=2;
q=[-1 1];
x=[-d/2 d/2];
y=[0 0];
dx=0.01;
X=(-d:dx:d);
Y=(-d:dx:d);
[X Y]=meshgrid(X,Y);
E=zeros(size(X));
for i=1:numel(q)
r=sqrt((X-x(i)).^2+(Y-y(i)).^2);
E=E+k*q(i)./r.^2;
end
E(isinf(E))=NaN;
figure;
contourf(X,Y,E);
axis image;
Hope it helps you. You can read the documentation of contourf to tweak the plot to your needs.

You need to give some more information in your question: What is the problem you are having? What have you tried?
However, assuming that z(i,j) is your electric field calculated on a 2d grid, just call contourf after your for loops as
contourf(z)

Related

Linear Support Vector Machine Implementation in MATLAB (from scratch)

I am looking for some help on determining the linear decision boundary between two classes.
I've taken a look at the search results with no luck.
Implementing a linear, binary SVM (support vector machine) is similar but not quite on the mark.
My question comes down to how to pull the correct line equation out of the weight vector.
Given a matrix of test data X=[Xa Xb], where Xa=[Nx2] && Xb=[Nx2] data samples.
These are in two classes (-1,1) saved in [Nx1] vector Y=[1 1 ... 1 -1 -1... -1]'
I use MATLAB's quadprog.m to solve the quadratic program...
I understand that we want to solve w1x1 + w2x2 + wo=0, so in my code I solve for W=[w1 w2]; and I solve for wo=1/Y1 - WX1^T.
When implemented my decision boundary plots as:
Clearly this is not what I want. The slope of the line looks legit, but I think I want to translate it north a little bit to optimize. In this picture the yellow dots are the support vectors.
It appears that I used the first data point, X(1,:) to be precise, and my line sucks. If I use different points it draws the line in different places, this makes sense algebraically, but how do i get the optimal boundary, not just a parallel boundary orthogonal to the weighting vector?
Thanks!
If you're interested in the code, here it is:
function [alph,w,wo,sv]=svm_binary(Class1,Class2)
x1=Class1;
x2=Class2;
% Combine data into one set
xt=[x1;x2];
% Create class labels
y=[ones(length(x1),1); -1.*ones(length(x2),1)];
N=length(xt);
% Scatter plot of original data class data points
figure
scatter(x1(:,1),x1(:,2));
hold on
scatter(x2(:,1),x2(:,2));
legend('Class1','Class2')
xlabel('x1')
ylabel('x2')
title('Class Data Scatter Plot')
% Data component of Langrangian dual
H=(xt*xt').*(y*y');
% Vector to flip signs
f=-ones(N,1);
%Constraint 1) a(i)>=0
A= -eye(N);
a=zeros(N,1);
% Constraint 2) sum[a(i)y(i)]=0
B=[y';zeros(N-1,N)];
b=zeros(N,1);
%Solve Quadratic Programming optimization for alpha
alph=quadprog(H+eye(N)*.001,f,A,a,B,b);
%Solve for W
w=(alph.*y)'*xt;
sv=[];
for i=1:length(xt)
if abs(alph(i))>=.0000001
sv=[sv i];
end
end
xtsv=xt(sv,:);
wo=1/y(1)-w*xt(1,:)';
if abs(w(1))<=.000001
y=-wo/w(2).*ones(round(max(xt(:,1))-min(xt(:,1))),1);
x=min(xt(:,2)):(max(xt(:,2))-min(xt(:,2)))/(length(y)-1):max(xt(:,2));
elseif abs(w(2))<=.000001
x=-wo/w(1).*ones(round(max(xt(:,2))-min(xt(:,2))),1);
y=min(xt(:,1)):(max(xt(:,1))-min(xt(:,1)))/(length(x)-1):max(xt(:,1));
else
x=round(min(xt(:,1))):round(max(xt(:,1)))
y=(w(1)/w(2)).*-x-wo/(w(2));
end
sv=[];
for i=1:length(xt)
if abs(alph(i))>=.0000001
sv=[sv i];
end
end
xtsv=xt(sv,:);
scatter(xtsv(:,1),xtsv(:,2),'fillled','markeredgecolor','black','markerfacecolor','yellow');
% y=-(w(1).*x)-wo
length(x)
length(y)
hold on
plot(x,y)

For loop in matlab plot

Hello i am having some problems understading basic plotting in matlab.
I can understand why you would use a for loop when plotting data?
Can anybody explain this to me?
I am making a simple linear plot. Is there any reason this should be inside a loop
If you are making a simple plot there is virtually no reason to use a loop.
If you check doc plot you will find that plot can take some vectors as input, or even matrices for more interesting situations.
Example:
x=0:0.01:1;
y=sin(x);
plot(x,y)
No there is no need in Matlab to use a for loop for plotting. If you are looking for a simple linear plot your code could look like this:
x=1:100;
y=3*x+4;
plot(x,y)
As you see there is no for loop needed. Same goes for nearly all plots and visualization.
A possible reason to use a for loop to plot thing may be having several data to plot in a single matrix. Say you have two matrix Ax (MxN) and Ay (MxN) where N the length of each data and M is the amount of different data wanted to plot. For example like in this case N is 201 and M is 3:
% Create Ax and Ay
Ax=meshgrid(0:0.1:20,1:3);
Ay=zeros(size(Ax));
% Sinusoidals with different frequencies
for k=1:3
Ay(k,:)=sin(k.*Ax(k,:));
end
% create colours
colorVec = hsv(3);
% Plot
hold on
for k=1:3
plot(Ax(k,:),Ay(k,:),'Color',colorVec(k,:))
end
hold off
You get:

Write Equation from Fit in Legend, Matlab

So, I've fitted an exponential curve to some data points using 'fit' and now I want to get the equation of the fitted curve in the Legend in the graph. How can I do that? I want to have an equation on the form y=Ce^-xt in the legend. Can I get the coefficients, C and x from the fitted curve and then put the equation inside the legend? Or can I get the whole equation written out in some way? I have many plotted graphs so I would be grateful if the method is not so much time consuming.
Edit: Perhaps I was unclear. The main problem is how I should get out the coefficients from the fitted line I've plotted. Then I want to have the equation inside the legend in my graph. Do I have to take out the coefficients by hand (and how can it be done?) or can Matlab write it straight out like in, for example, excel?
The documentation explains that you can obtain the coefficients derived from a fit executed as c = fit(...), as
coef=coeffvalues(c)
C=coef(1)
x=coef(2)
You can create your own legend as illustrated by the following example.
Defining C and x as the parameters from your fits,
% simulate and plot some data
t= [0:0.1:1];
C = 0.9;
x = 1;
figure, hold on
plot(t,C*exp(-x*t)+ 0.1*randn(1,length(t)),'ok', 'MarkerFaceColor','k')
plot(t,C*exp(-x*t),':k')
axis([-.1 1.2 0 1.2])
% here we add the "legend"
line([0.62 0.7],[1 1],'Linestyle',':','color','k')
text(0.6,1,[ ' ' num2str(C,'%.2f'),' exp(-' num2str(x,'%.2f') ' t) ' ],'EdgeColor','k')
set(gca,'box','on')
Example output:
You may have to adjust number formatting and the size of the text box to suit your needs.
Here is a piece of code that will display the fitted equation in the legend box. You can reduce the amount of digits in the legend by manipulating the sprintf option: %f to %3.2f for example.
%some data
load census
s = fitoptions('Method','NonlinearLeastSquares','Lower',[0,0],'Upper',[Inf,max(cdate)],'Startpoint',[1 1]);
f = fittype('a*(x-b)^n','problem','n','options',s);
%fit, plot and legend
[c2,gof2] = fit(cdate,pop,f,'problem',2)
plot(c2,'m');
legend(sprintf('%f * (x - %f)^%d',c2.a,c2.b,c2.n));
The command disp(c2) will display in the command window what is stored in the fit object. Also, by enabling the "datatip in edit mode" option (Matlab preferences, then Editor, then Display), you will have an instant view on the data stored by putting your mouse cursor over an object.
function [S]=evaFit(ffit)
S=sprintf('y=%s',formula(ffit));
S2='';
N=coeffnames(ffit);
V=coeffvalues(ffit);
for i= 1:numcoeffs(ffit)
S2=sprintf('%s %c=%f',S2, string(N(i)), V(i));
end
S=sprintf('%s%s',S, S2);
end

How to create 3D joint density plot MATLAB?

I 'm having a problem with creating a joint density function from data. What I have is queue sizes from a stock as two vectors saved as:
X = [askQueueSize bidQueueSize];
I then use the hist3-function to create a 3D histogram. This is what I get:
http://dl.dropbox.com/u/709705/hist-plot.png
What I want is to have the Z-axis normalized so that it goes from [0 1].
How do I do that? Or do someone have a great joint density matlab function on stock?
This is similar (How to draw probability density function in MatLab?) but in 2D.
What I want is 3D with x:ask queue, y:bid queue, z:probability.
Would greatly appreciate if someone could help me with this, because I've hit a wall over here.
I couldn't see a simple way of doing this. You can get the histogram counts back from hist3 using
[N C] = hist3(X);
and the idea would be to normalise them with:
N = N / sum(N(:));
but I can't find a nice way to plot them back to a histogram afterwards (You can use bar3(N), but I think the axes labels will need to be set manually).
The solution I ended up with involves modifying the code of hist3. If you have access to this (edit hist3) then this may work for you, but I'm not really sure what the legal situation is (you need a licence for the statistics toolbox, if you copy hist3 and modify it yourself, this is probably not legal).
Anyway, I found the place where the data is being prepared for a surf plot. There are 3 matrices corresponding to x, y, and z. Just before the contents of the z matrix were calculated (line 256), I inserted:
n = n / sum(n(:));
which normalises the count matrix.
Finally once the histogram is plotted, you can set the axis limits with:
xlim([0, 1]);
if necessary.
With help from a guy at mathworks forum, this is the great solution I ended up with:
(data_x and data_y are values, which you want to calculate at hist3)
x = min_x:step:max_x; % axis x, which you want to see
y = min_y:step:max_y; % axis y, which you want to see
[X,Y] = meshgrid(x,y); *%important for "surf" - makes defined grid*
pdf = hist3([data_x , data_y],{x y}); %standard hist3 (calculated for yours axis)
pdf_normalize = (pdf'./length(data_x)); %normalization means devide it by length of
%data_x (or data_y)
figure()
surf(X,Y,pdf_normalize) % plot distribution
This gave me the joint density plot in 3D. Which can be checked by calculating the integral over the surface with:
integralOverDensityPlot = sum(trapz(pdf_normalize));
When the variable step goes to zero the variable integralOverDensityPlot goes to 1.0
Hope this help someone!
There is a fast way how to do this with hist3 function:
[bins centers] = hist3(X); % X should be matrix with two columns
c_1 = centers{1};
c_2 = centers{2};
pdf = bins / (sum(sum(bins))*(c_1(2)-c_1(1)) * (c_2(2)-c_2(1)));
If you "integrate" this you will get 1.
sum(sum(pdf * (c_1(2)-c_1(1)) * (c_2(2)-c_2(1))))

How to simulate and draw electric fields in Matlab with contourf?

I'd like to know how to draw a graph with 2 electric charges Q and -Q and their total E, for a specific point (eg (4,5)), with contour f..
My M-file actually scans the area (from -3x to 3x) and calculates E for every spot, stores it in a table, but after this, I don't know how to use contourf to draw it..
syms i
syms j
syms d
d=input('dwse thn timi tou d,ths apostashs')
j=0
i=0
for j=-d:d/1000:d
j=j+1
for i=-d:d/1000:d
i=i+1
z=(i,j)
end, end
Based on Coulomb's law, the electric field created by a single, discrete charge q at a distance r is given by:
E=q/(4*pi*e0*r.^2);
If you have several charges you can use the superposition principle and add the contribution of each charge.
The only thing left to do is to create a grid to compute the electrical field. For this you can use tha Matlab function meshgrid.
A simple example in Matlab would be:
k=1/4/pi/8.854e-12;
d=2;
q=[-1 1];
x=[-d/2 d/2];
y=[0 0];
dx=0.01;
X=(-d:dx:d);
Y=(-d:dx:d);
[X Y]=meshgrid(X,Y);
E=zeros(size(X));
for i=1:numel(q)
r=sqrt((X-x(i)).^2+(Y-y(i)).^2);
E=E+k*q(i)./r.^2;
end
E(isinf(E))=NaN;
figure;
contourf(X,Y,E);
axis image;
Hope it helps you. You can read the documentation of contourf to tweak the plot to your needs.
You need to give some more information in your question: What is the problem you are having? What have you tried?
However, assuming that z(i,j) is your electric field calculated on a 2d grid, just call contourf after your for loops as
contourf(z)