I am trying to fit a curve for a set of points using numpy and scipy libraries but am getting a closed curve as shown below.
Could anyone let me know how to fit a curve without closing curve?
The code I followed is:
import numpy as np
from scipy.interpolate import splprep, splev
import matplotlib.pyplot as plt
coords = np.array([(3,8),(3,9),(4,10),(5,11),(6,11), (7,13), (9,13),(10,14),(11,14),(12,14),(14,16),(16,17),(17,18),(18,18),(19,18), (20,19),
(21,19),(22,20),(23,20),(24,21),(26,21),(27,21),(28,21),(30,21),(32,20),(33,20),(32,17),(33,16),(33,15),(34,12), (34,10),(33,10),
(33,9),(33,8),(33,6),(34,6),(34,5)])
tck, u = splprep(coords.T, u=None, s=0.0, per=1)
u_new = np.linspace(u.min(), u.max(), 1000)
x_new, y_new = splev(u_new, tck, der=0)
plt.plot(coords[:,1], coords[:,0], 'ro')
plt.plot(y_new, x_new, 'b--')
plt.show()
Output:
I need output without joining the 1st and last point.
Thank you.
Just set per parameter to 0 in scipy.interpolate.splprep:
tck, u = splprep(coords.T, u=None, s=0.0, per=0)
Related
I have an experimental data with relative uncertainties. And I would applied a fourth degree polynomial considering a specified model with logarithms. The issue im facing is how can I get an uncertainty on the fit considering the experimental data. I have no idea how can I do this. Any suggestion would be appreciated.
Thank you.
import numpy as np
import matplotlib.pyplot as plt
x = [121.78, 244.69, 344.278, 411.1165, 778.904, 867.38, 964.079, 1112.076, 1212.948, 1299.142, 1408.013]
y = [2.98E-03, 2.18E-03, 1.64E-03, 1.79E-03, 8.09E-04, 7.54E-04, 6.80E-04, 6.11E-04, 5.83E-04, 5.49E-04, 5.01E-04]
error_abs = [4.72E-05, 3.64E-05, 2.63E-05, 3.38E-05, 1.38E-05, 1.50E-05, 1.15E-05, 1.06E-05, 1.66E-05, 1.51E-05, 8.41E-06] # y_err
# x and y in logarithms
t1 = np.log(x)
t2 = np.log(y)
l = np.linspace(np.min(t1),np.max(t1),1000)
p,cov = np.polyfit(t1,t2,4, cov=True)
fit = np.polyval(p,l)
plt.errorbar(x, y, yerr=error_abs, lw=0.5, capsize=2, capthick=0.5, linestyle='none', marker='s',markersize=3, label='efficiency', color='orange')
plt.plot(np.exp(l),np.exp(fit), label ='Fit')
plt.show()
print(np.sqrt(np.diag(cov)))
I am trying to fit some data with Gaussian fit. This data from lateral flow image. The fitted line (red) does not cover data. Please check my code. In the code x is just index. y actually real data.
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
y = np.array([2.22097081, 2.24776432, 2.35519896, 2.43780396, 2.49708355,
2.54224971, 2.58350984, 2.62965057, 2.68644093, 2.75454015,
2.82912617, 2.90423835, 2.97921199, 3.05864617, 3.14649922,
3.2430853 , 3.3471892 , 3.45919857, 3.58109399, 3.71275641,
3.84604379, 3.94884214, 3.94108998, 3.72148453, 3.28407665,
2.7651018 ])
x = np.linspace(1,np.mean(y),len(y))
n = len(x)
mean = sum(x*y)/n
sigma = np.sqrt(sum(y*(x-mean)**2)/n)
def gaus(x,a,x0,sigma):
return a*np.exp(-(x-x0)**2/(2*sigma**2))/(sigma*np.sqrt(2*np.pi))
popt,pcov = curve_fit(gaus,x,y,p0=[1,mean,sigma])
plt.figure()
plt.plot(x,y,'b+:',label='data')
plt.plot(x,gaus(x,*popt),'ro:',label='fit')
plt.legend()
plt.xlabel('Index')
plt.ylabel('Row Mean')
I was wondering if there's a way to find tangents to curve from discrete data.
For example:
x = np.linespace(-100,100,100001)
y = sin(x)
so here x values are integers, but what if we want to find tangent at something like x = 67.875?
I've been trying to figure out if numpy.interp would work, but so far no luck.
I also found a couple of similar examples, such as this one, but haven't been able to apply the techniques to my case :(
I'm new to Python and don't entirely know how everything works yet, so any help would be appreciated...
this is what I get:
from scipy import interpolate
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-100,100,10000)
y = np.sin(x)
tck, u = interpolate.splprep([y])
ti = np.linspace(-100,100,10000)
dydx = interpolate.splev(ti,tck,der=1)
plt.plot(x,y)
plt.plot(ti,dydx[0])
plt.show()
There is a comment in this answer, which tells you that there is a difference between splrep and splprep. For the 1D case you have here, splrep is completely sufficient.
You may also want to limit your curve a but to be able to see the oscilations.
from scipy import interpolate
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-15,15,1000)
y = np.sin(x)
tck = interpolate.splrep(x,y)
dydx = interpolate.splev(x,tck,der=1)
plt.plot(x,y)
plt.plot(x,dydx, label="derivative")
plt.legend()
plt.show()
While this is how the code above would be made runnable, it does not provide a tangent. For the tangent you only need the derivative at a single point. However you need to have the equation of a tangent somewhere and actually use it; so this is more a math question.
from scipy import interpolate
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-15,15,1000)
y = np.sin(x)
tck = interpolate.splrep(x,y)
x0 = 7.3
y0 = interpolate.splev(x0,tck)
dydx = interpolate.splev(x0,tck,der=1)
tngnt = lambda x: dydx*x + (y0-dydx*x0)
plt.plot(x,y)
plt.plot(x0,y0, "or")
plt.plot(x,tngnt(x), label="tangent")
plt.legend()
plt.show()
It should be noted that you do not need to use splines at all if the points you have are dense enough. In that case obtaining the derivative is just taking the differences between the nearest points.
from scipy import interpolate
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-15,15,1000)
y = np.sin(x)
x0 = 7.3
i0 = np.argmin(np.abs(x-x0))
x1 = x[i0:i0+2]
y1 = y[i0:i0+2]
dydx, = np.diff(y1)/np.diff(x1)
tngnt = lambda x: dydx*x + (y1[0]-dydx*x1[0])
plt.plot(x,y)
plt.plot(x1[0],y1[0], "or")
plt.plot(x,tngnt(x), label="tangent")
plt.legend()
plt.show()
The result will be visually identical to the one above.
I am trying to get a polynomial fit for my data. Currently, I am using polyfit from numpy to get the best fit in a loglog plot. But my goal is to get the data fit in a semilogy plot. My code looks as follows:
import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit
import scipy.optimize as optimization
l = [ 0.006, 0.01, 0.014, 0.024, 0.0346, 0.049, 0.0535, 0.0736, 0.11 ]
f = [5.3375903383330048, 60.531976422513054, 89.111502526131474, 47.132498501584969, 17.447001214543118, 5.2583622688081455, 3.7779565652126865, 1.0621247249682186, 0.1922152085619766]
logx = np.log(l)
logy = np.log(f)
coeffs = np.polyfit(logx,logy,deg=3)
poly = np.poly1d(coeffs)
yfit = lambda x: np.exp(poly(np.log(x)))
plt.loglog(l,yfit(l), ':')
plt.loglog(l,f, 'o')
plt.show()
I would appreciate if you suggest what changes do I have to make to get a semilogy best fit curve. Also if there is any other package in python, please mention them too.
I think this.
# log sacle
x2 = np.linspace(np.min(l), np.max(l), 1000)
y2log = poly(np.log(x2))
plt.loglog(x2,np.exp(y2log), ':')
plt.loglog(l,f, 'o')
plt.show()
I am using the below python code so as to bias an absolute sine wave. I would like to have only the crest part of the wave and not the trough part even after positive biasing.Here I am unable achieve continuous crest signal after positive biasing. Can any one help me in this?
Usage: Keeping the input signals above the threshold even during dynamic shift of threshold.
import matplotlib.pyplot as plt
import numpy as np
Bias=5;
x=np.linspace(-20,20,1000);
y=np.abs(np.sin(x)+Bias);
#Bias=np.zeros_like(x); # This is not working
y[(y<=Bias)]= Bias + y # This is not working
plt.plot(x,y)
plt.grid()
plt.show()
It is a litle bit unclear what you are asking... Maybe you want to try this:
import matplotlib.pyplot as plt
import numpy as np
Bias=5;
x = np.linspace(-20, 20, 1000);
y = np.abs(np.sin(x))
y = y + Bias
plt.plot(x, y)
plt.grid()
plt.show()
or this:
import matplotlib.pyplot as plt
import numpy as np
Bias=5;
x=np.linspace(-20,20,1000);
y=np.abs(np.sin(x) + Bias);
y[(y<=Bias)]= Bias
plt.plot(x,y)
plt.grid()
plt.show()