LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Sin Fit

is there a vi for regression fitting of sine functions?  like of the form y=A*sin(2*Pi*f+p*t).

thank you in advance.

lucas
0 Kudos
Message 1 of 22
(7,667 Views)
You can use the general Levenberg-Marquardt fitting VIs under Analyze -> Mathematics -> Curve Fitting.

0 Kudos
Message 2 of 22
(7,656 Views)
oh yes, i found it and understand the content on the help file.  i will code for it and test it.  i'll drop another reply to let you know how it went.  thank you very much.

lucas
0 Kudos
Message 3 of 22
(7,643 Views)
lucas,

I have found in some preliminary testing that fitting to sine is tricky. The Lev-Mar fit VIs work quite well if you have a portion of one cycle. If you have ten cycles it will not work unless the initial guesses are very close to the correct values.

I think it has to do with the fact that the partial derivatives of sin(2*Pi*f*t) with respect to f do not force the function to move toward the correct value for the fit. I am not working on this at the moment but intend to return to it some day.

Lynn
0 Kudos
Message 4 of 22
(7,625 Views)
yes, lynn, you are absolutely correct.  i had to calculate the initial parameters to get good fits.  i have been testing using four cycles and every so often, like 1 out of 8 times, it completely diverges.  i also found that i had to get very close to 2*pi*f*t to improve my results.

but ultimately i am using the fit to find the roots, t at y=0, values.  so partial fits are ok for me where i load the fit with 95% of one side of the sine wave, either the negative slope side or the positive slope side.  when i plot the "best nonlinear fit" points against the original raw sine data, it matches up beautifully.  however, when i attempt to solve for the equation at y=0 usng the "best fit coefficients", i get some ungodly roots.  like say the root should be like 2271.9.  when i solve, i will get -803,432.233.  and it is not a simple number of integer cycles because i tried those divisions and i am not get close to integer values.

so i am wondering how to solve for the damn equation now.

lucas
0 Kudos
Message 5 of 22
(7,611 Views)
oh yeah, the final equation that i entered into the Levenberg-Marquardt vi is "a*sin(w*x+p)+b"  where a, w, p, and b are the fit parameter and x is the independent.  a is estimated found (max-min)/2 from the raw sine array, w is estimated at 2*pi*f deal, p is estimated from the zero phase which is also calculated from the raw array, and b is estimated at min+a.

lucas
0 Kudos
Message 6 of 22
(7,610 Views)
my old hp calculator has a numerical root solver that lets me put in a best estimate for x and 'x' and solve for the equation.  does labview have a vi that we can enter a formula string, equate its parameters, give a best guess, and it solves for the root, y=0?

lucas
0 Kudos
Message 7 of 22
(7,608 Views)
Maybe fitting to sine is not the best choice if you want zero crossings. If you extract a segment with approximately one half cycle going from -peak to +peak and then fit a cubic equation (third order polynomial) to that, I suspect that the fit will be quite close and the zero crossing quite accurate. The cubic equation can be solved analytically so once you have the fit parameters (the polynomial coefficients), the root location can be calculated directly without using a root finder. The third order polynomial may have three zero crossings but only one should be within the data segment. This will probably work faster as well.

Lynn
0 Kudos
Message 8 of 22
(7,605 Views)
If all you need is the phase of the signal (zero crossings), you would likely get this information
more easily by simply taking an FFT. You can then find the largest amplitude component,
which would be the frequency that you are trying to detect. The phase of that component
is what you get from the sine function fitting. An FFT does not require parameter guessing
and is much faster than fitting.
0 Kudos
Message 9 of 22
(7,586 Views)
Lucas

What version of LabVIEW are you using?  Do you have any data you could share?  If you are using LabVIEW 8.0 or later, then there is a VI that could be a real help.  Take a look at Extract Multiple Tones.vi.  This is similar to the Extract Single Tone.vi, except it will find more than one tone.  It is also a diffent algorithm that the single tone extraction.  The DC offset in your signal will appear in the "multiple tone info" output as a very low frequency tone (milli-Hz to micro-Hz).  Even if you continue to use the Nonlinear Curve Fit.vi, this could give you a very good initial guess, particularly for the frequency.

You also mentioned using a numerical root finder to find the zero crossings.  Given your model (A*sin(wx+p)+b) it seems that you should be able to solve explicitly for x.
a*Sin(wx+p)+b = 0
Sin(wx+p) = -b/a
wx+p = InvSin(-b/a)
x=(InvSin(-b/a)-p)/w

This will give one level crossing (level of zero), and adding full periods will give every other crossing, but the alternate crossings are not half-periods from the crossing x, unless the offset in the model is zero. 
You could view the set of crossings as all x that satisfy:
a*Sin(wx+p+kPi) = 0 where k is an integer,

expanding in Sin and Cos:
a*[Sin(wx+p)*Cos(kPi) + Cos(wx+p)*Sin(kPi)] = 0
Sin(kPi)=0, so
aCos(kPi)Sin(wx+p)=0
let A=aCos(kPi)
solving for x as before gives:
x=(InvSin(-b/A)-p)/w

Using this approach and the Extract Multiple Tones.vi seems to give very good results for the zero crossings on some simple data I tried here (Sine + Gaussian Noise).

The use of local polynomial models will work but if you can involve the entire dataset in solving for a model then there is more "averaging" of the noise in the data and the results should be more robust.  If your data does not match the model well, or the model changes over the course of the data (non-stationary), then Lynn's approach is better.

Hope this helps.

-Jim
0 Kudos
Message 10 of 22
(7,568 Views)