-
-
Notifications
You must be signed in to change notification settings - Fork 8.4k
Allow setting frequency units for psd plots #32211
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?
Changes from all commits
4b43e6a
52fe0fa
740c249
b7a56e2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| Power Spectral Density | ||
| ~~~~~~~~~~~~~~~~~~~~~~ | ||
| An optional keyword *Funits* is added to `.Axes.psd` so | ||
| units that differ from the default 'Hz' can be specified. | ||
| This change is backward compatible (no change if the optional | ||
| keyword is omitted.) |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,30 @@ | ||||||
| Sampling frequency units can be specified for `.Axes.psd` | ||||||
| --------------------------------------------------------------- | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Should match the length of the title. |
||||||
|
|
||||||
| When creating a power spectral density (psd) plot, the units of the | ||||||
| sampling frequency can be specified. (Units were previously always | ||||||
| assumed to be Hz.) | ||||||
|
|
||||||
| :: | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you use the plot directive here, you automatically get the image that this code produces. See here for an example
https://matplotlib.org/devdocs/release/next_whats_new/pie_wedge_labels.html |
||||||
|
|
||||||
| import matplotlib.pyplot as plt | ||||||
| import numpy as np | ||||||
|
|
||||||
| # Sampling period in units of days | ||||||
| dt = 1/24 | ||||||
|
|
||||||
| # Create example signal: sinusoid with red noise | ||||||
| np.random.seed(19680801) # Fixing random state for reproducibility | ||||||
| t = np.arange(0, 20, dt) | ||||||
| nse = np.random.randn(len(t)) | ||||||
| r = np.exp(-t / 0.05) | ||||||
| cnse = np.convolve(nse, r) * dt | ||||||
| cnse = cnse[:len(t)] | ||||||
| s = 0.1 * np.sin(2 * np.pi * t) + cnse | ||||||
|
|
||||||
| # Show signal and power spectral density | ||||||
| fig, (ax0, ax1) = plt.subplots(2, 1, layout='constrained') | ||||||
| ax0.plot(t,s) | ||||||
| ax0.set(xlabel='Time (d)', ylabel='Signal') | ||||||
| ax1.psd(s, NFFT=256, Fs=1 / dt, Funits='cpd') | ||||||
| plt.show() | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8113,7 +8113,8 @@ def ecdf(self, x, weights=None, *, complementary=False, | |
| @_docstring.interpd | ||
| def psd(self, x, NFFT=None, Fs=None, Fc=None, detrend=None, | ||
| window=None, noverlap=None, pad_to=None, | ||
| sides=None, scale_by_freq=None, return_line=None, **kwargs): | ||
| sides=None, scale_by_freq=None, return_line=None, Funits=None, | ||
| **kwargs): | ||
| r""" | ||
| Plot the power spectral density. | ||
|
|
||
|
|
@@ -8147,6 +8148,10 @@ def psd(self, x, NFFT=None, Fs=None, Fc=None, detrend=None, | |
| return_line : bool, default: False | ||
| Whether to include the line object plotted in the returned values. | ||
|
|
||
| Funits : str, default: 'Hz' | ||
| Units for the sampling frequency *Fs*. It is used to label the | ||
| xaxis and yaxis. | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should have a |
||
| Returns | ||
| ------- | ||
| Pxx : 1-D array | ||
|
|
@@ -8194,19 +8199,21 @@ def psd(self, x, NFFT=None, Fs=None, Fc=None, detrend=None, | |
| """ | ||
| if Fc is None: | ||
| Fc = 0 | ||
| if Funits is None: | ||
| Funits = 'Hz' | ||
|
|
||
| pxx, freqs = mlab.psd(x=x, NFFT=NFFT, Fs=Fs, detrend=detrend, | ||
| window=window, noverlap=noverlap, pad_to=pad_to, | ||
| sides=sides, scale_by_freq=scale_by_freq) | ||
| freqs += Fc | ||
|
|
||
| if scale_by_freq in (None, True): | ||
| psd_units = 'dB/Hz' | ||
| psd_units = 'dB/%s' % Funits | ||
| else: | ||
| psd_units = 'dB' | ||
|
|
||
| line = self.plot(freqs, 10 * np.log10(pxx), **kwargs) | ||
| self.set_xlabel('Frequency') | ||
| self.set_xlabel('Frequency (%s)' % Funits) | ||
| self.set_ylabel('Power Spectral Density (%s)' % psd_units) | ||
| self.grid(True) | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -363,8 +363,8 @@ def _spectral_helper(x, y=None, NFFT=None, Fs=None, detrend_func=None, | |
| result[slc] *= scaling_factor | ||
|
|
||
| # MATLAB divides by the sampling frequency so that density function | ||
| # has units of dB/Hz and can be integrated by the plotted frequency | ||
| # values. Perform the same scaling here. | ||
| # has units of V**2/Hz, if x is measured in units of V and the sampling | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not familiar with either this code or MATLAB, so finding this a little confusing. Do we have |
||
| # frequency is measured in Hz. Perform the same scaling here. | ||
| if scale_by_freq: | ||
| result /= Fs | ||
| # Scale the spectrum by the norm of the window to compensate for | ||
|
|
@@ -470,10 +470,10 @@ def _single_spectrum_helper( | |
| `.detrend_mean`. 'linear' calls `.detrend_linear`. | ||
|
|
||
| scale_by_freq : bool, default: True | ||
| Whether the resulting density values should be scaled by the scaling | ||
| frequency, which gives density in units of 1/Hz. This allows for | ||
| integration over the returned frequency values. The default is True for | ||
| MATLAB compatibility.""") | ||
| Whether the resulting density values should be divided by the sampling | ||
| frequency, which gives density in units of 1/Hz, if the sampling rate | ||
| is measured in Hz. This allows for integration over the returned | ||
| frequency values. The default is True for MATLAB compatibility.""") | ||
|
|
||
|
|
||
| @_docstring.interpd | ||
|
|
||
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.
next_api_changesis for changes that are not backwards compatible, so this is not needed.next_whats_newis the correct place to advertise this.