# How to fit a curve to a sinusoidal wave

I am wondering how to fit a sinusoidal wave (approximation). I would like to fit it in the form: $y = A\sin(Bx + C) + D$ where $A,\,B,\,C$ and $D$ are constants. The only constants I really care about is A and B so that I can get the amplitude and time period..

Edit:

I think I should clarify.. The data that I will be fitting will likely be noisy, so I was thinking that sine fit might give me a more accurate reading for the amplitude than just taking the max and min values from the raw data..

-
How noisy? Levenberg-Marquardt (the method used in Numerical Recipes) can fail on fitting problems with really noisy data. Could you maybe include a sample plot of data you'll be dealing with? This is not even taking into account that trigonometric fitting is quite difficult due to the objective function potentially displaying many local minima... – J. M. May 3 '11 at 18:12

You need a nonlinear least-squares routine, available in any numerical analysis book. Obsolete versions of Numerical Recipes are available for free. You can get pretty good starting values by setting D as the average of all the data, A as the range of the data, and B and C from an FFT. It might be a little simpler to expand the sine to $A\sin(Bx)\cos C+A\cos(Bx)\sin C$ and define $E=A\cos C, F=A\sin C$, but I'm not sure.

-

If your data spans a whole number of periods, then you can just take the Fourier term with the largest amplitude. This will represent the best-fitting sine wave to your data in the least-squares sense, and you can get its amplitude, frequency and phase from the corresponding Fourier coefficients. This works because the Fourier basis is orthonormal, so the squared error resulting from discarding all but one Fourier term is proportional to the sum of the squared amplitudes of all the other terms.

If your data spans a non-whole number of periods, it's probably a harder problem. You could try taking the largest Fourier term as an initial guess and then do some kind of nonlinear optimization like in Ross's comment; maybe even simple-minded gradient descent might work.

-