Plotting a Parametric Spline Curve Using a Periodic Spline - matlab

I want to plot a curve like this using a periodic spline:
I have the following values:
And so, I have created the following matlab code to plot this function:
%initializing values
t = [1,2,3,4,5,6,7,8,9,10,11,12,13];
tplot = [1:0.1:13];
x = [2.5,1.3,-0.25,0.0,0.25,-1.3,-2.5,-1.3,0.25,0.0,-0.25,1.3,2.5];
y = [0.0,-0.25,1.3,2.5,1.3,-0.25,0.0,0.25,-1.3,-2.5,-1.3,0.25,0.0];
[a1, b1, c1, d1] = perspline2(t,x);
[a2, b2, c2, d2] = perspline2(t,y);
for i = 1:12
xx = linspace(x(i), x(i+1), 100);
xxx = a1(i) + b1(i)*(xx-x(i)) + c1(i)*(xx-x(i)).^2 ...
+ d1(i)*(xx-x(i)).^3;
yyy = a2(i) + b2(i)*(xx-x(i)) + c2(i)*(xx-x(i)).^2 ...
+ d2(i)*(xx-x(i)).^3;
h3=plot(xxx, yyy, 'r-');
hold on
end
plot(x,y,'k.', 'MarkerSize', 30)
hold off
With perspline2() looking like this:
function [a1,b1,c1,d1] = perspline2(xnot,ynot)
x = xnot';
y = ynot';
n = length(x) - 1;
h = diff(x);
diag0 = [1; 2*(h(1:end-1)+h(2:end)); 2*h(end)];
A = spdiags([[h;0], diag0, [0;h]], [-1, 0, 1], n+1, n+1);
% Do a little surgery on the matrix:
A(1,2) = 0;
A(1,end) = -1;
A(end,1) = 2*h(1);
A(end,2) = h(1);
dy = diff(y);
rhs = 6*[0; diff(dy./h); dy(1)/h(1)-dy(end)/h(end)];
m = A \ rhs; % Solve for the slopes, S''(x_i)
% Compute the coefficients of the cubics.
a1 = y;
b1 = dy./h - h.*m(1:end-1)/2 - h.*diff(m)/6;
c1 = m/2;
d1 = diff(m)./h/6;
So basically, I know that I must use a parametric spline in order to find the correct points to plot.
I use t = [1,2,3,4,5,6,7,8,9,10,11,12,13]; as my indexes. So, I find the coefficients for the cubic spline polynomial of t vs. x and then find the coefficients for t vs. y, and then I attempt to plot them against each other using values from t in order to plot the parametric curve. However, I keep getting this curve:
I am really not sure why this is occurring.
P.S I know I can use the matlab spline function but when I do, it results in the right cusp being a bit bigger than the other cusps. I want all cusps to be equal in size and the assignment says that we must use a cubic spline.
Any help is greatly appreciated.

Related

2d gaussian with matlab?

I want to draw a gaussian in two dimension centered in the middle of the matrix with matlab. Right now I am doing with
for i = 1:size2
for j = 1:size2
gauss(i,j)=A*exp(-1/(sigma^2)*((i-round(size2/2))^2+(j-round(size2/2))^2)); %gaussiana
end
end
but it can be extremely slow.
In matlab I have not found any function, what is the fastest way to do it? Is a mex file a valuable option?
Vectorizing the gaussian computation using meshgrid is relatively trivial.
There is even an Octave implementation in Wikipedia.
The implementation is:
[X, Y] = meshgrid(1:size2, 1:size2);
G = A*exp(-1/(sigma^2)*((Y-size2/2).^2 + (X-size2/2).^2));
Note: I replaced the round(size2/2) with size2/2 because the rounding is not part of the formula.
Trick for converting 1D gaussian into 2D gaussian:
For making the computation a little bit faster we can create 1D gaussian, and compute the 2D gaussian out of it:
x = 1:size2;
G1 = sqrt(A)*exp(-1/(sigma^2)*(x-size2/2).^2); % Create 1D gaussian
G2 = G1'*G1; % Compute the 2D gaussian out of 1D gaussian.
Testing:
size2 = 101;
A = 10;
sigma = 50;
gauss = zeros(size2);
for y = 1:size2
for x = 1:size2
gauss(y,x)=A*exp(-1/(sigma^2)*((y-size2/2)^2+(x-size2/2)^2)); %gaussiana
end
end
[X, Y] = meshgrid(1:size2, 1:size2);
G = A*exp(-1/(sigma^2)*((Y-size2/2).^2 + (X-size2/2).^2));
disp(['sum abs diff (G, gauss) = ' num2str(sum(abs(G(:) - gauss(:))))])
x = 1:size2;
G1 = sqrt(A)*exp(-1/(sigma^2)*(x-size2/2).^2);
G2 = G1'*G1;
disp(['sum abs diff (G1, G2) = ' num2str(sum(abs(G2(:) - G(:))))])
Output:
sum abs diff (G, gauss) = 0
sum abs diff (G1, G2) = 7.1436e-12
Update:
According to Cris comment "meshgrid is no longer needed".
Since MATLAB r2016b we can use the following code:
X = 1:size2;
Y = X';
G = A*exp(-1/(sigma^2)*((Y-size2/2).^2 + (X-size2/2).^2));
The implementation relays on a feature named "implicit singleton expansion" or Implicit Expansion.

How do I plot linear decision boundary in matlab

plotted two different dataset
I have 2 different dataset that have different mu and sigma, and X vector such as [1.8; 1.8]. And also I know probability of each classes that P(ω1)= P(ω2) = 1/2
I want to ploting linear decision boundary between these two dataset but I don't have any idea have to do. My code is down below, here
X = [1.8; 1.8];
u1 = [1;1]; u2 = [3;3];
s1 = [1 0;0 1]; s2 = [1 0;0 1];
Pr1 = 1/2;
Pr2 = 1/2;
r = mvnrnd(u1,s1,500);
plot(r(:,1), r(:,2), '+r');
hold on
r = mvnrnd(u2,s2,500);
plot(r(:,1), r(:,2), '+b');
hold on
grid on
W1 = (u1')/(s1(1,1))^2;
W10 = (u1'*u1)/(-2*s1(1,1)) + log(Pr1);
g1 = W1'.*X + W10;
W2 = (u2')/(s2(1,1))^2;
W20 = (u2'*u2)/(-2*s2(1,1)) + log(Pr2);
g2 = W2'.*X + W20;
Is there someone who can give any idea to me please?
The trick is to calculate two points of the decision boundary you want to plot.
W1_W2 = W2 - W1; % vector from W1 to W2
W1_W2_average = (W2 + W1)/2; % point in the middle between W1 and W2
W1_W2_orthogonal = [-W1_W2(2) W1_W2(1)]; % vector orthogonal to W1_W2
points = [W1_W2_average - 2*W1_W2_orthogonal; W1_W2_average + 2*W1_W2_orthogonal]; % Two points on the line you want to plot
plot(points(:, 1), points(:, 2)); %plot the line
Note that I am not very familiar with classification problems. I might have forgotten some terms in the calculation of the decision boundary.
I solved decision problem, in detailed
First I defined parametric function with parameters x1 and x2 such as
g = #(x1,x2)
then in order to plotting decision boundary realized that g1-g2 = 0 equation such as
e = #(x1,x2) (W1*[x1;x2] + w10 - W2*[x1;x2] - w20)
ezplot(g, [-xlim xlim -ylim ylim])
and done

Matlab line fitting: Singular value decomposition (SVD)

I tried to fit a line using 2D points. By using the SVD, I've successfully fit lines. However, in the one case, I failed to fit lines. Please, give me some advise and let me know the reasons.
% Data
X = [487,520.40,553.81,587.22,620.63,654.04,500,533.01,566.02,599.03,642,674.61,707.22,517,552.35,587.71,647,682.35,717.71,522,555.97,589.94,623.91,657.88];
Y = [521,558.20,595.40,632.60,669.80,707.00,533,570.55,608.10,645.66,695,732.90,770.80,564,599.35,634.71,694,729.35,764.71,562,598.68,635.37,672.06,708.75];
% b1*x + b2*y +b3 = 0
M = [X', Y', ones(size(X'))];
[~, ~, V] = svd(M);
B = V(:, 3);
b1 = B(1);
b2 = B(2);
b3 = B(3);
% Draw points
figure(111)
hold on;
plot(X, Y, 'ro');
% Draw line
minX = min(X);
maxX = max(X);
valY_minX = -(b3 + b1*minX) / b2;
valY_maxX = -(b3 + b1*maxX) / b2;
Pt1 = [minX; valY_minX];
Pt2 = [maxX; valY_maxX];
plot([Pt1(1), Pt2(1)], [Pt1(2), Pt2(2)]);
I've got succeed fit the line when I changed to 'V(:, 2)'. Why the second largest eigen value brings the best solution??

Optim-nonlinear equation in matlab code

I updated the question to clarify it more. Here is a graph:
For the curve in the attached photo, I hope to draw the curve. I have its equation and it is after simplification will be like this one
% Eq-2
(b*Y* cos(v) + c - k*X*sin(v))^2 + ...
sqrt(k*X*(cos(v) + 1.0) + b*Y*sin(v))^2) - d = 0.0
Where:
v = atan((2.0*Y)/X) + c
and b, c, d and k are constants.
from the attached graph,
The curve is identified in two points:
p1 # (x=0)
p2 # (y=0)
I a new on coding so accept my apologize if my question is not clear.
Thanks
So, after your edit, it is a bit more clear what you want.
I insist that your equation needs work -- the original equation (before your edit) simplified to what I have below. The curve for that looks like your plot, except the X and Y intercepts are at different locations, and funky stuff happens near X = 0 because you have numerical problems with the tangent (you might want to reformulate the problem).
But, after checking your equation, the following code should be helpful:
function solve_for_F()
% graininess of alpha
N = 100;
% Find solutions for all alphae
X = zeros(1,N);
options = optimset('Display', 'off');
alpha = linspace(0, pi/2, N);
x0 = linspace(6, 0, N);
for ii = 1:numel(alpha)
X(ii) = fzero(#(x)F(x, alpha(ii)), x0(ii), options);
end
% Convert and make an X-Y plot
Y = X .* tan(alpha);
plot(X, Y,...
'linewidth', 2,...
'color', [1 0.65 0]);
end
function fval = F(X, alpha)
Y = X*tan(alpha);
% Please, SIMPLIFY in the future
A = 1247745517111813/562949953421312;
B = 4243112111277797/4503599627370496;
V = atan2(2*Y,X) + A;
eq2 = sqrt( (5/33*( Y*sin(V) + X/2*(cos(V) + 1) ))^2 + ...
(5/33*( Y*cos(V) - X/2* sin(V) ))^2 ) - B;
fval = eq2;
end
Results:
So, I was having fun with this (thanks for that)!
Different question, different answer.
The solution below first searches for the constants causing the X and Y intercepts you were looking for (p1 and p2). For those constants that best fit the problem, it makes a plot, taking into account numerical issues.
In fact, you don't need eq. 1, because that's true always for any curve -- it's just there to confuse you, and problematic to use.
So, here it is:
function C = solve_for_F()
% Points of interest
px = 6;
py = 4.2;
% Wrapper function; search for those constants
% causing the correct X,Y intercepts (at px, py)
G = #(C) abs(F( 0, px, C)) + ... % X intercept at px
abs(F(py, 0, C)); % Y intercept at py
% Initial estimate, based on your original equation
C0 = [5/33
1247745517111813/562949953421312
4243112111277797/4503599627370496
5/66];
% Minimize the error in G by optimizing those constants
C = fminsearch(G, C0);
% Plot the solutions
plot_XY(px, py, C);
end
function plot_XY(xmax,ymax, C)
% graininess of X
N = 100;
% Find solutions for all alphae
Y = zeros(1,N);
X = linspace(0, xmax, N);
y0 = linspace(ymax, 0, N);
options = optimset('Display', 'off',...,...
'TolX' , 1e-10);
% Solve the nonlinear equation for each X
for ii = 1:numel(X)
% Wrapper function for fzero()
fcn1 = #(y)F(y, X(ii), C);
% fzero() is probably the fastest and most intuitive
% solver for this problem
[Y(ii),~,flag] = fzero(fcn1, y0(ii), options);
% However, it uses an algorithm that easily diverges
% when the function slope is large. For those cases,
% solve with fminsearch()
if flag ~= 1
% In this case, the minimum of the absolute value
% is searched for (which should be zero)
fcn2 = #(y) abs(fcn1(y));
Y(ii) = fminsearch(fcn2, y0(ii), options);
end
end
% Now plot the X,Y solutions
plot(X, Y,...
'linewidth', 2,...
'color', [1 0.65 0]);
xlabel('X'), ylabel('Y')
axis([0 xmax+.1 0 ymax+.1])
end
function fval = F(Y, X, C)
% Unpack constants
b = C(1); d = C(3);
c = C(2); k = C(4);
% pre-work
V = atan2(2*Y, X) + c;
% Eq. 2
fval = sqrt( (b*Y*sin(V) + k*X*(cos(V) + 1))^2 + ...
(b*Y*cos(V) - k*X* sin(V) )^2 ) - d;
end

Inverse fast fourier transform in MATLAB

My MATLAB code for fft and ifft below has a problem with the inverse Fourier signal y not matching the in put signal x. Is there any solution to resolve this?
N = 1000;
t0 = 1e-13;
tau = 2*1e-14;
n = [0:t0/40:2*1e-13-t0/40];
f0 = 3*1e8/(150*1e-9);
x = cos(2*pi*f0*n);
x = x.*exp((-(n-t0).^2)./(tau^2));
X = abs(fft(x,N));
F = [-N/2 : N/2 - 1]/N;
X = fftshift(X);
y=ifft(X,80);
figure(3)
plot(n,y)
I see a number of issues here:
N = 1000;
t0 = 1e-13;
tau = 2*1e-14;
n = [0:t0/40:2*1e-13-t0/40];
f0 = 3*1e8/(150*1e-9);
x = cos(2*pi*f0*n);
x = x.*exp((-(n-t0).^2)./(tau^2));
% X = abs(fft(x,N)); <-- Not seen this technique before, and why N=1000?
% try something more like:
X = fft(x);
F = [-N/2 : N/2 - 1]/N;
% this is fine to shift and plot the function
Xshifted = fftshift(X);
plot( abs( Xshifted ) )
% now you're taking the inverse of the shifted function, not what you want
% y=ifft(X,80); also not sure about the 80
y = ifft(X);
figure(3)
plot(n,y)
figure(4)
plot( n, x ); hold on; plot( n, y, 'o' )
That's all I see at first. HTH!
If you take the absolute value of the fft, you destroy the phase information needed to reconstruct the original signal, i.e. the moment you compute
X = abs(fft(x,N));
You cannot go back via ifft, because now you only have the magnitude.
Also, the inverse transformation only works if you use the same number of FFT bins with NFFT>=length(x).
y=ifft(fft(x));
should be exactly the same as x.