Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Incorrect and Inconsistent output of function PSD when scale_by_freq=False #4328

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
e-q opened this issue Apr 12, 2015 · 3 comments
Closed
Milestone

Comments

@e-q
Copy link
Contributor

e-q commented Apr 12, 2015

If we state scale_by_freq=False, then we are asking for the power spectrum of the signal, instead of the power spectral density; i.e. units of V^2 instead of V^2/Hz, for example.

mlab.psd, which actually is mlab._spectral_helper under the hood, does not return the expected value of the power in a sinusoid. Furthermore, in contrast to the PSD case, it does not correct for the energy of the signal lost to the window function, meaning that the results differ depending on the window used.

Here's an illustration. If we have a simple signal of a cosine oscillation happening at 100Hz with amplitude of 10, we would expect the power spectrum result at 100Hz to be 50, regardless of the window used. (A cosine like this that is identically zero at each integer second means we can use one second FFTs and compare the rectangular window to the hanning window, without worrying about any distortion)

In MATLAB:

fs=2048;
tt=[0:1/fs:60-1/fs];
x = 10*cos(2*pi*100*tt);
[pR, f]=pwelch(x, ones(1,fs), 0, fs, fs, 'power');
[pH, f]=pwelch(x, hann(fs), 0, fs, fs, 'power');

gives pR(101)==50 and pH(101)==50.000..., as expected.

In matplotlib.mlab:

fs = 2048
tt = np.arange(fs*64)/float(fs)
x = 10*np.cos(2*np.pi*100*tt)
# One second FFT segments
psdHann, ff = mlab.psd(x, Fs=fs, NFFT=fs, window=mlab.window_hanning, scale_by_freq=False)
psdRect, ff = mlab.psd(x, Fs=fs, NFFT=fs, window=mlab.window_none, scale_by_freq=False)

gives psdRect[100] == 102400, which too large by a factor of nfft and psdHann[100] == 68233.3, which differs further by some window correction factor.

I came across this in scipy/scipy#4682, where I was adapting the code for inclusion in scipy's signal processing repertoire. There, I used scale = 1.0 / win.sum()**2 for the power spectrum case. I haven't looked for the exact places where _spectral_helper should be fixed, at this time.

@tacaswell tacaswell added this to the next point release milestone Apr 12, 2015
@tacaswell
Copy link
Member

Thanks for reporting this. I assume that you will fix this for scipy and then we can back-port what ever that fix is?

@tacaswell
Copy link
Member

@e-q What is the state of this?

@e-q
Copy link
Contributor Author

e-q commented Jul 6, 2015

Sorry about that! PR submitted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants