I've followed several examples I found online but I still don't get a smooth fitted curve and I'm not sure why. The curve should mostly follow the data points however the frequency is a lot higher and just doesn't seem to be working and I'm not sure why. Not sure what else to say, I'm just a bit lost..
import scipy as sp
import matplotlib.pyplot as plt
from scipy import linalg, optimize
X=sp.array([0.0,15.0,30.0,45.0,60.0,75.0,90.0,105.0,120.0,135.0,150.0,165.0,180.0,195.0,210.0,225.0,240.0,255.0,270.0,285.0,300.0,315.0,330.0,345.0,360.0])
Y=sp.array([196.3,282.0,337.0,347.0,312.0,240.0,152.0,69.0,15.3,1.1,33.0,105.4,195.4,195.4,286.0,345.0,362.0,256.0,162.0,75.0,14.9,1.3,35.1,105.2,194.9])
#DEBUG-------------------
print("Y len: ",len(Y))
print("X len: ",len(X))
#------------------------
def fit_func(x,a,c):
cosinesquare = a*sp.cos(x+c)**2
return cosinesquare
po, po_cov = sp.optimize.curve_fit(fit_func, X, Y, p0=[50,360])
#DEBUG------------------
print("po:",po)
print("po[0]: ",po[0])
print("po[1]: ",po[1])
#-----------------------
plt.scatter(X, Y, marker="x", label="Data")
plt.plot(X,fit_func(X, *po), label="Fitted func")
plt.xlabel("Angle of transmission axis")
plt.ylabel("voltage (mV)")
plt.grid()
plt.legend()
plt.show()
The other answer works, but the real issue is that you need to convert from degrees to radians. You can add sp.pi/180
to do the conversion in your function.
import scipy as sp
import matplotlib.pyplot as plt
from scipy import linalg, optimize
X=sp.array([0.0,15.0,30.0,45.0,60.0,75.0,90.0,105.0,120.0,135.0,150.0,165.0,180.0,195.0,210.0,225.0,240.0,255.0,270.0,285.0,300.0,315.0,330.0,345.0,360.0])
Y=sp.array([196.3,282.0,337.0,347.0,312.0,240.0,152.0,69.0,15.3,1.1,33.0,105.4,195.4,195.4,286.0,345.0,362.0,256.0,162.0,75.0,14.9,1.3,35.1,105.2,194.9])
#DEBUG-------------------
print("Y len: ",len(Y))
print("X len: ",len(X))
#------------------------
def fit_func(x,a,c):
cosinesquare = a*sp.cos((x+c)*sp.pi/180.)**2
return cosinesquare
po, po_cov = sp.optimize.curve_fit(fit_func, X, Y, p0=[50,360])
#DEBUG------------------
print("po:",po)
print("po[0]: ",po[0])
print("po[1]: ",po[1])
#-----------------------
plt.scatter(X, Y, marker="x", label="Data")
plt.plot(X,fit_func(X, *po), label="Fitted func")
plt.xlabel("Angle of transmission axis")
plt.ylabel("voltage (mV)")
plt.grid()
plt.legend()
plt.show()