Search code examples
pythonscipytrigonometrycurve-fitting

Scipy Curve fit, trigonometry model


I am trying to model a specific trig function given x and y values from the table. The function I am supposed to find parameters to is of the form $A\cdot sin(x\cdot t + ph) +d$. There $A$ is the amplitude, $x $ is the period, $ph$ is the phase shift and $d$ vertical shift. Here $t$ is the variable.

 from pylab import * 
 from scipy.optimize import curve_fit
 time = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23]
 waterlevel = [125,199,223,176,101,73,109,181,219,188,122,85]
 
 def h(t,x, A , phi, d):
      return A*sin(x*t + phi) + d
 
 x, A, phi, d = curve_fit(h, time ,waterlevel, p0 = [0,71,-57,150]) # p0 are my approximations
 
 print("A =", round(A,2))
 print("phi =", round(phi,2))
 print("d =", round(d,2))
 print("x =", round(x,2))

 plot(tid, vannstand, "o")
 xlabel("Time (hours)")
 ylabel("water level (cm)")
 t = linspace(0,24,1000)
 plot(t, h(t,x,A,phi,d), "r")
 show()

The trick here was to determine $x$, the phase shift, without the initial guess. I have tried with the above code, but I get a message that there are not enough values to unpack in the seventh line (expected 4, got 2). Any ideas as to my mistakes and potential steps towards determining the values?


Solution

  • A method to fit sinusoidal functions without initial guess is explained with examples pp. 21-36 in https://fr.scribd.com/doc/14674814/Regressions-et-equations-integrales . The simplified version is shown below :

    enter image description here

    The symbols are different from the symbols that you use. It is easy to see the relationships. Especially the symbol "omega" is "x" in your formula.

    The above method provides an approximate value of omega ('your "x"). If one want a more accurate value according to somme specified criteria of fitting (LMSE or LMAE or LMRE or other) one have to proceed an iterative non-linear regression starting from the approximates values found above.

    Example :

    enter image description here

    Note :

    The above method without initial guess is based on the fitting of an integral equation. Numerical integration is involved ( computation of Sk and SSk). If the number of points is low the numerical integrations introduce some deviations which reduce the accuracy of the result. This is the case in the above example with only 12 points. Nevertheless the result is generally sufficient to correctly initiate further iterative calculus of nonlineaer regression. Below the result (criteria LMSE) :

    enter image description here

    Of course the fitting is better. The discrepancy is mainly due to the too small number of points.