Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions doc/api/next_api_changes/development/32211_CDH.rst
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.)
30 changes: 30 additions & 0 deletions doc/release/next_whats_new/new_psd_feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
Sampling frequency units can be specified for `.Axes.psd`
---------------------------------------------------------------

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.)

::

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()
3 changes: 3 additions & 0 deletions galleries/examples/statistics/psd_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
ax0.set_xlabel('Time (s)')
ax0.set_ylabel('Signal')
ax1.psd(s, NFFT=512, Fs=1 / dt)
# If dt had other units (e.g. days instead of seconds),
# then the units of Fs (e.g. cycles per day or cps) can be specified
# by the keyword Funits (e.g. Funits='cpd') in psd.

plt.show()

Expand Down
13 changes: 10 additions & 3 deletions lib/matplotlib/axes/_axes.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down Expand Up @@ -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 *Fc*. It is used to label the
xaxis and yaxis.

Returns
-------
Pxx : 1-D array
Expand Down Expand Up @@ -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)

Expand Down
1 change: 1 addition & 0 deletions lib/matplotlib/axes/_axes.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,7 @@ class Axes(_AxesBase):
scale_by_freq: bool | None = ...,
return_line: bool | None = ...,
data: DataParamType = ...,
Funits: str | None = ...,
**kwargs
) -> tuple[np.ndarray, np.ndarray] | tuple[np.ndarray, np.ndarray, Line2D]: ...
def csd(
Expand Down
2 changes: 2 additions & 0 deletions lib/matplotlib/pyplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -4070,6 +4070,7 @@ def psd(
sides: Literal["default", "onesided", "twosided"] | None = None,
scale_by_freq: bool | None = None,
return_line: bool | None = None,
Funits: str | None = None,
*,
data: DataParamType = None,
**kwargs,
Expand All @@ -4086,6 +4087,7 @@ def psd(
sides=sides,
scale_by_freq=scale_by_freq,
return_line=return_line,
Funits=Funits,
**({"data": data} if data is not None else {}),
**kwargs,
)
Expand Down
Loading