Course 6.2Lesson 3 of 3
Real readings are noisy. The FFT in numpy shows which frequencies a signal holds and gives a first guess. Then scipy's curve_fit finds the amplitude, frequency and phase of the best sine, with an error for each. Read too slowly and a fast wave looks slow.
Try the code and the simulations beside the lesson.
A sensor follows a swinging spring and records its displacement every 0.05 s. That gives 40 readings in 2 s. Each reading is a little off, because of noise. The true motion is a sine, and you want three numbers from it: the amplitude , the frequency and the phase .
scipy.optimize.curve_fit(model, t, y, p0=guess) changes the unknowns until the sum of the squared misses is as small as possible. You give it a function model(t, A, f, phi), the readings and a first guess p0. It returns two things:
popt, the best values of the unknowns;pcov, a table from which the errors come: np.sqrt(np.diag(pcov)) gives one error for each unknown.Here is a fit to clean data, so that you can see the idea in a few lines:
It prints [0.5 1. 0.5]. The fit finds the three numbers that made the data, starting from a rough guess.
curve_fit works downhill from p0. For a sine, the sum of squared misses has many dips, one for each frequency that nearly fits. A first frequency far from the truth can slide into the wrong dip. You need a guess for that is already close.
The fast Fourier transform, FFT, splits a signal into sine waves of different frequencies.
np.fft.rfft(y) does the splitting. np.abs(...) of it gives the size of each frequency.np.fft.rfftfreq(n, d) gives the frequencies, for readings that are seconds apart.It prints 3.0 Hz: the frequency of the tallest bar of the spectrum. This is the first guess for curve_fit.
One reading every seconds can show only frequencies below . This is the Nyquist limit. A wave needs at least two readings in each cycle. Above the limit, the wave folds back and looks like a slower one. This is aliasing.
Here a 9 Hz wave is read 10 times each second. The dots fall on a 1 Hz wave:
It prints 1.0 Hz. The FFT cannot tell the readings from those of a 1 Hz wave. The cure is to read faster, more than twice the highest frequency in the signal.
The program makes 40 noisy readings, takes a first guess from the FFT, and fits a sine with curve_fit. It prints each unknown with its error. The picture shows what it finds: the readings and the fitted sine above, and the FFT below.
pcov as the errors. pcov holds squares. The errors are np.sqrt(np.diag(pcov)).2 * np.pi * f * t, the fit returns a frequency in Hz, not in rad/s.rfftfreq gives Hz only when d is in seconds.curve_fit(model, t, y, p0=[A, f, phi]).np.sqrt(np.diag(pcov)).np.abs(np.fft.rfft(y)).Try each one on your own first. If you are stuck, open a hint. Then check with Show the answer.
np.sqrt(np.diag(pcov)) give?Every lesson is open to read. Enrolling also lets you:
Log in to join the discussion.
Loading…
This lesson is free to read. Enroll free to keep your place and take the tests.