Search code examples
pythoncurve-fitting

Why Curve_fit is not fit the data?


I'm try to use cosine function as my model to fit the data, some how it doesn't work.

Here is my code:

import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt


def model(x,a,psi,b):
    return a*np.cos(x + psi)+b
err_y = 0.5
err_x = 2
x = np.arange(10, 370,20)
x_r = x* (np.pi/180)
y = np.array([5.7, 7.9, 8, 6.6, 4.4, 1.3, 0.09, 1.2, 2.9, 5.9, 7.8, 9, 7, 4.2, 1.5, 0.17, 0.57, 2.5])
error = err_y * np.ones(y.size)


popt, pcov = curve_fit(model, x_r, y,p0 = (4, 3.14, 4), sigma = error,absolute_sigma = True)
print(popt)
plt.scatter(x,y)
plt.errorbar(x, y, yerr=err_y, fmt='none', c='k')
plt.xlabel('Angle(degree)')
plt.ylabel('Readout (V)')
plt.plot(x, model(x_r, *popt), color='red')

enter image description here

I tried many different initial guess for the parameters, but none of them work.


Solution

  • Your data has TWO cycles in 0 to 360 degrees - but your fitting function only allows for ONE.

    Try allowing for a frequency inside the cosine, as well as the phase.

    import numpy as np
    from scipy.optimize import curve_fit
    import matplotlib.pyplot as plt
    
    
    def model(x,a,omega,psi,b):
        return a*np.cos(omega*x + psi)+b
    err_y = 0.5
    err_x = 2
    x = np.arange(10, 370,20)
    x_r = x* (np.pi/180)
    y = np.array([5.7, 7.9, 8, 6.6, 4.4, 1.3, 0.09, 1.2, 2.9, 5.9, 7.8, 9, 7, 4.2, 1.5, 0.17, 0.57, 2.5])
    error = err_y * np.ones(y.size)
    
    
    popt, pcov = curve_fit(model, x_r, y,p0 = (4, 2.0, 3.14, 4), sigma = error,absolute_sigma = True)
    print(popt)
    plt.scatter(x,y)
    plt.errorbar(x, y, yerr=err_y, fmt='none', c='k')
    plt.xlabel('Angle(degree)')
    plt.ylabel('Readout (V)')
    plt.plot(x, model(x_r, *popt), color='red')
    plt.show()
    

    Output (the angular frequency comes out as 1.98... or, effectively, 2)

    [4.16352559 1.98440219 4.77715943 4.26330405]
    

    enter image description here