I'm refering to the following post : Using scipy.signal.spectral.lombscargle for period discovery
I realize the answer given correct for certain case.
# imports the numerical array and scientific computing packages
import numpy as np
import scipy as sp
from scipy.signal import spectral
# generates 100 evenly spaced points between 1 and 1000
time = np.linspace(1, 1000, 100)
# computes the sine value of each of those points
mags = np.sin(time)
# scales the sine values so that the mean is 0 and the variance is 1 (the documentation specifies that this must be done)
scaled_mags = (mags-mags.mean())/mags.std()
# generates 1000 frequencies between 0.01 and 1
freqs = np.linspace(0.01, 1, 1000)
# computes the Lomb Scargle Periodogram of the time and scaled magnitudes using each frequency as a guess
periodogram = spectral.lombscargle(time, scaled_mags, freqs)
# returns the inverse of the frequence (i.e. the period) of the largest periodogram value
print "1/2pi = " + str(1/(2*np.pi))
print "Frequency = " + str(freqs[np.argmax(periodogram)] / 2.0 / np.pi)
The following is printed. Is fine. I guess. The reason we divide the lombscargle
result with 2pi
is that, we need to convert radian to frequency. (f = radian / 2pi)
1/2pi = 0.159154943092
Frequency = 0.159154943092
However, thing seems goes wrong for the following case.
# imports the numerical array and scientific computing packages
import numpy as np
import scipy as sp
from scipy.signal import spectral
# generates 100 evenly spaced points between 1 and 1000
time = np.linspace(1, 1000, 100)
# computes the sine value of each of those points
mags = np.sin(2 * time)
# scales the sine values so that the mean is 0 and the variance is 1 (the documentation specifies that this must be done)
scaled_mags = (mags-mags.mean())/mags.std()
# generates 1000 frequencies between 0.01 and 1
freqs = np.linspace(0.01, 1, 1000)
# computes the Lomb Scargle Periodogram of the time and scaled magnitudes using each frequency as a guess
periodogram = spectral.lombscargle(time, scaled_mags, freqs)
# returns the inverse of the frequence (i.e. the period) of the largest periodogram value
print "1/pi = " + str(1/(np.pi))
print "Frequency = " + str(freqs[np.argmax(periodogram)] / 2.0 / np.pi)
The following is being printed.
1/pi = 0.318309886184
Frequency = 0.0780862900972
Seem incorrect. Any step that I had missed out?
pyplot. psd() function is used to plot power spectral density. In the Welch's average periodogram method for evaluating power spectral density (say, Pxx), the vector 'x' is divided equally into NFFT segments. Every segment is windowed by the function window and detrended by the function detrend.
The Lomb–Scargle periodogram is a method that allows efficient computation of a Fourier-like power spectrum estimator from such unevenly sampled data, resulting in an intuitive means of determining the period of oscillation.
I actually thought that nperseg is the number of time localised points and nfft is the number of frequency used.
The Lomb-Scargle periodogram (named for Lomb (1976) and Scargle (1982)) is a classic method for finding periodicity in irregularly-sampled data. It is in many ways analogous to the more familiar Fourier Power Spectral Density (PSD) often used for detecting periodicity in regularly-sampled data.
You are rightfully expecting the peak to show up at 1 / pi
, but the highest frequency you are testing is 1 / 2 / pi
... Try the following single change :
freqs = linspace(0.01, 3, 3000)
and now the output is the expected:
1/pi = 0.318309886184
Frequency = 0.318311478264
Note, though, that if you plot periodogram
against freqs / 2 / np.pi
, the graph looks like this:
So for a more complicated signal, you cannot rely on just looking for the max
of periodogram to find the dominant frequency, because the harmonics may fool you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With