1

As this question confirmed, Python doesn't currently have a sum of sines function like MATLAB.

I am looking to curve fit a 4th-order sinusoid in Python. Here is the MATLAB solution:

ft = fittype('sin4');
opts = fitoptions('Method', 'NonlinearLeastSquares');
[fitresult, gof] = fit(xData, yData, ft, opts);

% values for [a1, b1, ..., c4] are calculated

% fitted result
x=1:length(yData);
y=a1*sin(b1*x+c1) + a2*sin(b2*x+c2) + a3*sin(b3*x+c3) + a4*sin(b4*x+c4);

I can create a 1st-order sinusoidal fit with this solution (adapted):

def fit_sin(tt, yy):
    '''Fit sinewave to input time sequence'''
    tt = numpy.array(tt)
    yy = numpy.array(yy)
    ff = numpy.fft.fftfreq(len(tt), (tt[1]-tt[0]))
    Fyy = abs(numpy.fft.fft(yy))
    guess_freq = abs(ff[numpy.argmax(Fyy[1:])+1])
    guess_amp = numpy.std(yy) * 2.**0.5
    guess_offset = numpy.mean(yy)
    guess = numpy.array([guess_amp, 2.*numpy.pi*guess_freq, 0., guess_offset])
    def sinfunc(t, A, w, p, c):  return A * numpy.sin(w*t + p) + c
    popt, pcov = scipy.optimize.curve_fit(sinfunc, tt, yy, p0=guess)
    A, w, p, c = popt
    f = w/(2.*numpy.pi)
    fitfunc = lambda t: A * numpy.sin(w*t + p) + c
    return {"amp": A, "omega": w, "phase": p, "offset": c, "freq": f, "period": 1./f, "fitfunc": fitfunc, "maxcov": numpy.max(pcov), "rawres": (guess,popt,pcov)}

x = np.arange(0, len(yData))
res = fit_sin(x, yData)
y = res['fitfunc'](x)

So far I have tried iterating by entering the 1st-order output parameters (amp, omega, and phase) as input parameters p0 = (a1, b1, and c1) to a 2nd-order version of fit_sin(), and working my way up to a 4th-order.

However, this is very inefficient and the results did not match the MATLAB solution. Suggestions for how to proceed would be appreciated.

Mirka
  • 11
  • 3
  • try [scipy.optimize.least_squares](https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.least_squares.html). I am not sure but it is closest thing I found to Matlab method (nonlinear, least_squres) – dankal444 Dec 05 '22 at 13:19

0 Answers0