Matlab horizontal asymptote being calculated incorrectly - matlab

From an lsqcurve fit function I am trying to calculate the horizontal asymptote of a sigmoidal curve over the data range. The code I am using to do this and convert the output to double precision works and is as follows:
time = [0,0.166666666666667,0.333333333333333,0.500000000000000,0.666666666666667,0.833333333333333,1,1.16666666666667,1.33333333333333,1.50000000000000,1.66666666666667,1.83333333333333,2,2.16663888888889,2.33330555555556,2.49997222222222,2.66663888888889,2.83330555555556,2.99997222222222,3.16663888888889,3.33330555555556,3.49997222222222,3.66663888888889,3.83330555555556,3.99997222222222,4.16663888888889,4.33330555555556,4.49997222222222,4.66663888888889,4.83330555555556,4.99997222222222,5.16663888888889,5.33327777777778,5.49997222222222,5.66661111111111,5.83327777777778,5.99994444444444,6.16661111111111,6.33327777777778,6.49994444444444,6.66661111111111,6.83327777777778,6.99994444444444,7.16661111111111,7.33327777777778,7.49994444444444,7.66661111111111,7.83327777777778,7.99994444444444,8.16661111111111,8.33327777777778,8.49994444444445,8.66661111111111,8.83325000000000,8.99991666666667,9.16658333333333,9.33325000000000,9.49991666666667,9.66658333333333,9.83325000000000,9.99991666666667,10.1665833333333,10.3332500000000,10.4999166666667,10.6665833333333,10.8332500000000,10.9999166666667,11.1665833333333,11.3332500000000,11.4999166666667,11.6665833333333,11.8332222222222,11.9998888888889,12.1665555555556,12.3332222222222,12.4998888888889,12.6665555555556,12.8332222222222,12.9998888888889,13.1665555555556,13.3332222222222,13.4998888888889,13.6665555555556,13.8332222222222,13.9998888888889,14.1665555555556,14.3332222222222,14.4998888888889,14.6665555555556,14.8332222222222,14.9998611111111,15.1665277777778,15.3331944444444,15.4998611111111];
Abs=[0.0756333346168200,,0.0822666635115941,0.101066668828328,0.125066662828128,0.147433335582415,0.169966672857602,0.192199997603893,0.211166655023893,0.231433339416981,0.256133330365022,0.279866663118203,0.295566670596600,0.309466672440370,0.323400000731150,0.335233343144258,0.348299992581209,0.359700001776218,0.371433332562447,0.383333327869574,0.394433322052161,0.404166663686434,0.413666687905788,0.423499998946985,0.432733344535033,0.443266667425633,0.453899989525477,0.463699989020824,0.475066669285297,0.485300009449323,0.495999989410241,0.504966656366984,0.514033327500025,0.523766654233138,0.532566664119562,0.541033337513606,0.550333333512147,0.559733323752880,0.567733330031236,0.575466672579447,0.583399988710880,0.591433353722096,0.597833327949047,0.604699979225794,0.610233349104722,0.616733354826768,0.622800009946028,0.628666676580906,0.634199996789297,0.638966679573059,0.644799992442131,0.650733329355717,0.654566655556361,0.661333315074444,0.666366661588351,0.671233326196671,0.675699991484483,0.679433315992355,0.682733337084452,0.686333330969016,0.689166650176048,0.693133344252904,0.697366672257582,0.699333322544893,0.702233329415321,0.705400002499422,0.707699996729692,0.709999985992909,0.711533337831497,0.712800003588200,0.713633326192697,0.714666672050953,0.714533333977064,0.713999989132086,0.714266665279865,0.714066684246063,0.714266670246919,0.713733327885469,0.713066659867764,0.712200003365676,0.711600005626679,0.710400002698104,0.710399977862835,0.709799999992053,0.708366667230924,0.706933336953322,0.706766667465369,0.706199998656909,0.704266687234243,0.703333348035812,0.702399998903275,0.701133318245411,0.700166669984659,0.698799995084604,0.697700018684069];
u=linspace(0,15.49986111,500);
v=pchip(time,Abs,u);
p0 = [0.075633335,0.05,0.01]; %First value = Abs value at t=0
options=optimset('MaxFunEvals',10000,'MaxIter',5000,'Display','iter');
[p,error,residual]=lsqcurvefit(#gompertz,p0,time,Abs,[],[],options)
syms x t
f=p(1)*exp(-exp(((p(2)*exp(1))/p(1))*(p(3)-t)+1));
f1=diff(f,t); %Find first derivative of equation W wrt t
f2=diff(f,t,2); %Find second derivative wrt t and to allow inflection point to be defined
crit_pts = solve(f1); %Find local maxima and minima
crit_pts=double(crit_pts);
flimit = limit(f,inf); %Find find horizontal asymptote of function f by taking limit of f as x approaches infinity
function_horizontal_asymptote=double(limit);
The 'gompertz' function called is coded as follows:
function y = gompertz(p,t)
y=p(1)*exp(-exp(((p(2)*exp(1))/p(1))*(p(3)-t)+1));
According to the Matlab documentation I have read
flimit = limit(f,inf);
should yield the correct answer but and appear towards the end of the time course, however the result I get is (shown by the yellow marker):
Am I calculating this incorrectly?
Thank you for your time,
Laura

Related

Where did i do wrong when i tried to approximatee this data using polynomial?

I am starting to learn numerical analysis using MATLAB in my course. so far we have covered polynomial interpolation (spline, polyfit, constraint spline, etc.) I was doing this practice question and I can not get the correct answer. I have uploaded the code I used and the question, where did I do wrong? thanks in advance!
close all; clear all; clc;
format long e
x = linspace(0,1,8);
xplot = linspace(0,1);
f = #(x) atan(x.*(x+1));
y_val = f(xplot);
c = polyfit(x,f(x),7);
p = polyval(c,0.7);
err = abs(f(0.7)-p)/(f(0.7))
The question I encountered is seen in the picture
After some playing around, it seems to be a matter of computing the absolute error instead of the relative absolute error.
The code below yields the desired answer. And yes, it is pretty unclear from the question which error is intended.
% Definitions
format long e
x = linspace(0,1,8)';
xplot= linspace(0,1);
f = #(x) atan(x.*(x+1));
y_val = f(xplot);
% Degree of polynomial
n = 7;
% Points to evaluate function
point1 = 0.5;
point2 = 0.7;
% Fit
c= polyfit(x,f(x),n);
% Evaluate
approxPoint1 = polyval(c, point1);
approxPoint2 = polyval(c, point2);
% Absolute errors
errPoint1 = abs( f(point1) - approxPoint1)
errPoint2 = abs( f(point2) - approxPoint2)
What you did wrong was :
mixing absolute and relative values when calculating errors to feed resulting variable err.
incorrectly placing abs() parentheses when calculating err: Your abs() only fixes the numerator, but then the denominator. To obtain |f(0.7)| you also need another abs(f(0.7))
for point x=0.7 instead of
err = abs(f(0.7)-p)/(f(0.7))
could well simply be
err = abs(f(.7)-p));
you only calculate err for assessment point 0.5 . In order to choose among the possible candidates of what seems to be a MATLAB Associate test multichoice answer, one needs err on 0.5 and err on 0.7 and then match the pair in the correct order, among all offered possible answers.
Although it's common practice to approach polynomial approximation of N points with an N-1 degree polynomial, it's often possible to approximate below satisfactory error with lower degree polynomials than N-1.
Lower degree polynomials means less calculations, less time spent approximating points. If one obtains a fair enough approximation with for instance a degree 4 polynomial, why waste time calculating an approximation with a higher degree all the way up to N-1?
Since the question does not tell what degree should have the approximating polynomial, you have to find it sweeping all polynomial degrees from 1 to up to a reasonable order.
The last error I found is that you have used linspace without specifying amount of points, MATLAB then takes by default 100 points hoping it's going to be ok.
Well, in your question 100 points is way too low an amount of points as I am going to show after supplying the following lines, as mentioned in previous point, sweeping all possible approximating polynomials, NOT on default 100 points you tacitly chose.
np=8; % numel(x) amount supplied points
N=1e3; % amount points x grid we build to measure f(x)
x= linspace(0,1,np);
xplot = linspace(0,1,N);
f = #(x) atan(x.*(x+1)); % function to approximate
y_val = f(xplot); % f(x)
xm=[.5 .7]; % points where to asses error
% finding poly coeffs
err1=zeros(2,np+2); % 1st row are errors on x=.5, 2nd row errors on x=.7
figure(1);
ax1=gca
hp1=plot(xplot,y_val)
grid on;
hp1.LineWidth=3;
hp1.Color='r';
hold on
for k=1:1:np+2
c = polyfit(x,f(x),k);
p_01 = polyval(c,xm(1));
err1(1,k) = abs(f(xm(1))-p_01);
% err(1,k) = abs((f(0.5)-p_05)/(f(0.5)))
p_02 = polyval(c,xm(2));
err1(2,k) = abs(f(xm(2))-p_02);
% err(2,k) = abs((f(0.7)-p_07)/(f(0.7)))
plot(x,polyval(c,x),'LineWidth',1.5); %'Color','b');
end
err1
.
.
The only pair of errors matching in the correct order are indeed those of polynomial order 7, but the total smallest error corresponds to the approximating polynomial of order 6.
What happens when taking linspace without defining a large enough amount of points? let's have a look:
np=8; % numel(x) amount supplied points
% N=1e3; % amount points x grid we build to measure f(x)
x= linspace(0,1,np);
xplot = linspace(0,1); %,N);
f = #(x) atan(x.*(x+1)); % function to approximate
y_val = f(xplot); % f(x)
xm=[.5 .7]; % points where to asses error
% finding poly coeffs
err1=zeros(2,np+2); % 1st row are errors on x=.5, 2nd row errors on x=.7
figure(1);
ax1=gca
hp1=plot(xplot,y_val)
grid on;
hp1.LineWidth=3;
hp1.Color='r';
hold on
for k=1:1:np+2
c = polyfit(x,f(x),k);
p_01 = polyval(c,xm(1));
err1(1,k) = abs(f(xm(1))-p_01);
% err(1,k) = abs(f(0.5)-p_05)/abs(f(0.5))
p_02 = polyval(c,xm(2));
err1(2,k) = abs(f(xm(2))-p_02);
% err(2,k) = abs(f(0.7)-p_07)/abs(f(0.7))
plot(x,polyval(c,x),'LineWidth',1.5); %'Color','b');
end
err1
With only 100 points all errors come up way too large, not a single error anywhere near 1e-5 or 1e-6.
This is why one couldn't tell which pair to go for, because all obtained values where at least 5 orders of magnitude away from landing zone.
I was about to include a plot with legend, but the visualization of this particular approach is in this case and in my opinion at best misleading, as in both plots for 100 and 1000 points, at 1st glance, both look as if the errors should be similar regardless of the amount of grid points used.
But as shown above 1e2 points cannot approximate the function,
it's like pitch dark, looking for something and pointing torch 180 from where we should be aiming at, not a chance to spot it.
Yet 1e3 grid points produce a pair of errors matching one of the possible answers, this is option D.
I hope it helps, thanks for reading my answer.

Analytical Fourier transform vs FFT of functions in Matlab

I have adapted the code in Comparing FFT of Function to Analytical FT Solution in Matlab for this question. I am trying to do FFTs and comparing the result with analytical expressions in the Wikipedia tables.
My code is:
a = 1.223;
fs = 1e5; %sampling frequency
dt = 1/fs;
t = 0:dt:30-dt; %time vector
L = length(t); % no. sample points
t = t - 0.5*max(t); %center around t=0
y = ; % original function in time
Y = dt*fftshift(abs(fft(y))); %numerical soln
freq = (-L/2:L/2-1)*fs/L; %freq vector
w = 2*pi*freq; % angular freq
F = ; %analytical solution
figure; subplot(1,2,1); hold on
plot(w,real(Y),'.')
plot(w,real(F),'-')
xlabel('Frequency, w')
title('real')
legend('numerical','analytic')
xlim([-5,5])
subplot(1,2,2); hold on;
plot(w,imag(Y),'.')
plot(w,imag(F),'-')
xlabel('Frequency, w')
title('imag')
legend('numerical','analytic')
xlim([-5,5])
If I study the Gaussian function and let
y = exp(-a*t.^2); % original function in time
F = exp(-w.^2/(4*a))*sqrt(pi/a); %analytical solution
in the above code, looks like there is good agreement when the real and imaginary parts of the function are plotted:
But if I study a decaying exponential multiplied with a Heaviside function:
H = #(x)1*(x>0); % Heaviside function
y = exp(-a*t).*H(t);
F = 1./(a+1j*w); %analytical solution
then
Why is there a discrepancy? I suspect it's related to the line Y = but I'm not sure why or how.
Edit: I changed the ifftshift to fftshift in Y = dt*fftshift(abs(fft(y)));. Then I also removed the abs. The second graph now looks like:
What is the mathematical reason behind the 'mirrored' graph and how can I remove it?
The plots at the bottom of the question are not mirrored. If you plot those using lines instead of dots you'll see the numeric results have very high frequencies. The absolute component matches, but the phase doesn't. When this happens, it's almost certainly a case of a shift in the time domain.
And indeed, you define the time domain function with the origin in the middle. The FFT expects the origin to be at the first (leftmost) sample. This is what ifftshift is for:
Y = dt*fftshift(fft(ifftshift(y)));
ifftshift moves the origin to the first sample, in preparation for the fft call, and fftshift moves the origin of the result to the middle, for display.
Edit
Your t does not have a 0:
>> t(L/2+(-1:2))
ans =
-1.5000e-05 -5.0000e-06 5.0000e-06 1.5000e-05
The sample at t(floor(L/2)+1) needs to be 0. That is the sample that ifftshift moves to the leftmost sample. (I use floor there in case L is odd in size, not the case here.)
To generate a correct t do as follows:
fs = 1e5; % sampling frequency
L = 30 * fs;
t = -floor(L/2):floor((L-1)/2);
t = t / fs;
I first generate an integer t axis of the right length, with 0 at the correct location (t(floor(L/2)+1)==0). Then I convert that to seconds by dividing by the sampling frequency.
With this t, the Y as I suggest above, and the rest of your code as-is, I see this for the Gaussian example:
>> max(abs(F-Y))
ans = 4.5254e-16
For the other function I see larger differences, in the order of 6e-6. This is due to the inability to sample the Heaviside function. You need t=0 in your sampled function, but H doesn't have a value at 0. I noticed that the real component has an offset of similar magnitude, which is caused by the sample at t=0.
Typically, the sampled Heaviside function is set to 0.5 for t=0. If I do that, the offset is removed completely, and max difference for the real component is reduced by 3 orders of magnitude (largest errors happen for values very close to 0, where I see a zig-zag pattern). For the imaginary component, the max error is reduced to 3e-6, still quite large, and is maximal at high frequencies. I attribute these errors to the difference between the ideal and sampled Heaviside functions.
You should probably limit yourself to band-limited functions (or nearly-band-limited ones such as the Gaussian). You might want to try to replace the Heaviside function with an error function (integral of Gaussian) with a small sigma (sigma = 0.8 * fs is the smallest sigma I would consider for proper sampling). Its Fourier transform is known.

What is wrong with my lagrange multiplier matlab code?

I want to find the two farthest points lying on a closed curve with respect to a line. Lagrange multiplier seems to be do the job. But something is wrong with my code: I have 10 solution points (length(xsol)=10, some are repeated so the picture has only 7) and only two of them are what I want (with red ticks). Why would some points not lie on the curve?
syms x y L
g = #(x,y) x^2+2*x*y^2+y^6-1;
h = #(x,y) -4*x+y; % to max or min this such that g=0 is satisfied
gradg = jacobian(g,[x,y]); gradh = jacobian(h,[x,y]);
lagr = gradh - L*gradg;
[L,xsol,ysol]=solve(lagr(1),lagr(2),g);
plot(xsol,ysol,'bo')
What is wrong?
Lagrange multiplier gives local max, local min and also complex solutions. To get the farthest two points, we need one more step: evaluate the function values of all the 'solutions', find the indices with respect to the maximum and the minimum and finally we have the two points.
xsolreal=real(double(xsol)); % take the real part for giving accurate results
ysolreal=real(double(ysol));
fnvalue=zeros(1,length(xsol));
for i=1:length(xsol)
fnvalue(i)=-4*xsolreal(i)+ysolreal(i); % function value of the given line
end
gmax=find(fnvalue == max(fnvalue(:)));
gmin=find(fnvalue == min(fnvalue(:)));
x1=xsolreal(gmax);
y1=ysolreal(gmax);
x2=xsolreal(gmin);
y2=ysolreal(gmin);

Matlab: cumsum or cumtrapz which is appropriate for time integral?

I have a time varying signal (i.e. a pulse) which I need to calculate the time integral (integrated over the whole of the pulse) for and then evaluate the max./final integral value.
To investigate the appropriate function I have defined a square wave in MATLAB:
t=0:0.1:10;
x=square(t);
with amplitude varying between -1 and +1 (length of x is 101).
If I plot a = cumsum(x) and b = cumtrapz(t,x) I find similar shaped (saw-tooth) plots but
max(a) = 33
and
max(b) = 3.2
I'm not sure which is the appropriate integral final value (maximum) to use?

Plotting a closed interal function MATLAB

I need a help. I have to generate a curve using MATLAB. The plot is defined by the formula (an analytic expression) :-
where, the meaning of the variables are as follows: R is the distributed resistive function, S is the distributive conductive function, k is the sheet resistance and r(x,y) is the distance between *
(x,y)*, and the perimeter dl with the integration made around all the perimeter of the chip.
A squared foil as shown in the figure with sides (a) 10 arbitrary units long and an unitary unit sheet resistance (k=1 ohm) is used for our consideration. The plot of the function R(x,y) is supposed to come out like this...
I literally have no clue how to plot this function. I could not even get the idea how to define the distance function r(x,y) with respect to dl. On top of that it is complicated further by the closed integral. Please help me. Any help in even simplifying the expression is also welcome. Is there any possible closed form expression for such a square structure ?
Thanks in advance. The link to the paper is here. paper here
Reconstructing the math
The definition of the function R is not particularly clear, but I guess what they mean is:
With dOmega being the boundary of the foil and p a point p = [px,py] on the foil.
Imagine that for a point p on the sheet you are computing R(p) by going around the boundary of the foil (what they call the perimeter), your position being q, and integrating one divided by the distance from you (q) to the point p multiplied by k.
I guess you could analytically compute the integral for this rectangular sheet, but if you just want to plot the function, you could simply approximate the integral by defining a finite number of points on the boundary, evaluating the integrand in those points, then taking the mean and multiplying by the perimeter. [The same way you could approximate integral(f(x), x=0...pi) by pi*(f(0)+f(pi/2)+f(pi))/3]
Alternative representation using coordinates:
If you are only familiar with integrals along the real line in coordinate representation you could write this in the following way, which is frankly quite UGGGLY:
Plotting an approximation
%% Config:
xlen = 10;
ylen = 10;
k = 1;
%% Setting up points on the boundary of the square
x = linspace(0,xlen,50);
y = linspace(0,ylen,50);
perimeter = 2*(xlen+ylen);
boundary = [x(1)*ones(length(y),1), y'
x', y(1)*ones(length(x),1); ...
x(end)*ones(length(y),1), y'; ...
x', y(end)*ones(length(x),1)];
%% Function definition
norm2 = #(X) sqrt(sum(X.^2,2));
R = #(p) 1/(perimeter*mean(1./(k*norm2(bsxfun(#minus,boundary,p)))));
%% Plotting
[X_grid,Y_grid] = ndgrid(x,y);
R_grid = zeros(size(X_grid));
for ii = 1:length(x)
for jj = 1:length(y)
R_grid(ii,jj) = R([x(ii),y(jj)]);
end
end
surf(X_grid, Y_grid, R_grid);
axis vis3d;
This will give you the following plot: