-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
bugfix: scaling of windows with negative coefficients #22828
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
base: main
Are you sure you want to change the base?
bugfix: scaling of windows with negative coefficients #22828
Conversation
For proper scaling of the magnitude a division by the sum of all window elements is needed. To be able to handle complex window coefficients an abs() was introduced in a622508 which falsifies the scaling for windows with negative coefficients. Most prominently the flattop window. A proper type check is introduced to handle both cases correctly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for opening your first PR into Matplotlib!
If you have not heard from us in a while, please feel free to ping @matplotlib/developers
or anyone who has commented on the PR. Most of our reviewers are volunteers and sometimes things fall through the cracks.
You can also join us on gitter for real-time discussion.
For details on testing, writing docs, and our review process, please see the developer guide
We strive to be a welcoming and open project. Please follow our Code of Conduct.
Thanks! Makes sense! It would be good with a test for this so that it is not reintroduced. (Maybe it is a good idea to use the tests introduced in #8582, but not remove the ticklabels so that one actually see the effect of normalizing correctly.) |
@oscargus Can you please be in charge of final approval on this one? My biggest concern is that this is the correct (from a domain expect point of view) thing to do. |
Hello @oscargus, |
This needs a test, preferable for the flattop window. I don't fully parse the second point other than to note that one-sided spectra should definitely have twice the amplitude of the one side to account for the implied variance of the y shown negative side. As noted a few times Matplotlib should spin power spectra functionality out to a separate project and deprecate as a main library. It's pretty orthogonal to plotting and complicated enough that it deserves its own proper sets of docs and testing. |
Btw, yes, open a separate issue for the magnitude related issue. |
Here is my take on the window aspect. The reason for scaling the window should be that the gain in the passband should be one. This is obtained by normalizing with Regarding PSD, I do not have that strong opinions/knowledge, so I do not have much to add there. I can see both arguments being relevant. So better to open a new issue for that. |
The window in spectral analysis is multiplied by the whole data block. It is not convolved with the data like a filter. The variance of the data block before and after should be the same if the underlying process variance is not changing with time (stationary). I don't understand who uses complex windows or why. You likely would not use it for a single power spectra and I'm not sure what the convention should be. |
@oscargus I've pushed this to 3.8, please push back to 3.7 if you think this should go in. |
I think this fix is OK for a magnitude spectrum, but definitely not for power spectral density. At least according to the script implementation. But unless I'm reading it wrong our |
I checked this, and so far as I can tell in #24821 the window including flattop is being applied correctly. Moving to draft until further clarification... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the same error occurs in the psd code.
The source of the idea you can have a complex window would be interesting - I suspect this was just an error that was not caught because most windows are >0.
This all definitely needs tests. I would suggest simple mean of the spectra of Gaussian random numbers for different windows, including flattop.
@@ -395,7 +395,11 @@ def _spectral_helper(x, y=None, NFFT=None, Fs=None, detrend_func=None, | |||
elif mode == 'psd': | |||
result = np.conj(result) * result | |||
elif mode == 'magnitude': | |||
result = np.abs(result) / np.abs(window).sum() | |||
result = np.abs(result) | |||
if np.iscomplexobj(window): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you need to check for complex windows here.
👋🏻 Hi @lucasisonline ! Can we help you move this forward? If you have questions, feel free to ping. Thanks! |
PR Summary
The magnitude scaling is incorrect for windows with negative coefficients.
For proper scaling of the magnitude a division by the sum
of all window elements is needed.
To be able to handle complex window coefficients an abs()
was introduced in 76c4d84
which falsifies the scaling for windows with negative
coefficients. Most prominently the flattop window.
A proper type check is introduced to handle both cases
correctly.
PR Checklist
Tests and Styling
pytest
passes).flake8-docstrings
and runflake8 --docstring-convention=all
).Documentation
doc/users/next_whats_new/
(follow instructions in README.rst there).doc/api/next_api_changes/
(follow instructions in README.rst there).