Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit aec1e5b

Browse filesBrowse files
authored
Merge pull request #8582 from vollbier/magnitude_spectrumScaling
API: Changed normalization in _spectral_helper() to obtain consistent scaling
2 parents 3a58953 + ee1c40d commit aec1e5b
Copy full SHA for aec1e5b

File tree

Expand file treeCollapse file tree

7 files changed

+34
-4
lines changed
Filter options
Expand file treeCollapse file tree

7 files changed

+34
-4
lines changed
+31Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
Correct scaling of :func:`magnitude_spectrum()`
2+
```````````````````````````````````````````````
3+
4+
The functions :func:`matplotlib.mlab.magnitude_spectrum()` and :func:`matplotlib.pyplot.magnitude_spectrum()` implicitly assumed the sum
5+
of windowing function values to be one. In Matplotlib and Numpy the
6+
standard windowing functions are scaled to have maximum value of one,
7+
which usually results in a sum of the order of n/2 for a n-point
8+
signal. Thus the amplitude scaling :func:`magnitude_spectrum()` was
9+
off by that amount when using standard windowing functions (`Bug 8417
10+
<https://github.com/matplotlib/matplotlib/issues/8417>`_ ). Now the
11+
behavior is consistent with :func:`matplotlib.pyplot.psd()` and
12+
:func:`scipy.signal.welch()`. The following example demonstrates the
13+
new and old scaling::
14+
15+
import matplotlib.pyplot as plt
16+
import numpy as np
17+
18+
tau, n = 10, 1024 # 10 second signal with 1024 points
19+
T = tau/n # sampling interval
20+
t = np.arange(n)*T
21+
22+
a = 4 # amplitude
23+
x = a*np.sin(40*np.pi*t) # 20 Hz sine with amplitude a
24+
25+
# New correct behavior: Amplitude at 20 Hz is a/2
26+
plt.magnitude_spectrum(x, Fs=1/T, sides='onesided', scale='linear')
27+
28+
# Original behavior: Amplitude at 20 Hz is (a/2)*(n/2) for a Hanning window
29+
w = np.hanning(n) # default window is a Hanning window
30+
plt.magnitude_spectrum(x*np.sum(w), Fs=1/T, sides='onesided', scale='linear')
31+

‎lib/matplotlib/axes/_axes.py

Copy file name to clipboardExpand all lines: lib/matplotlib/axes/_axes.py
+1-2Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6666,8 +6666,7 @@ def magnitude_spectrum(self, x, Fs=None, Fc=None, window=None,
66666666
66676667
scale : [ 'default' | 'linear' | 'dB' ]
66686668
The scaling of the values in the *spec*. 'linear' is no scaling.
6669-
'dB' returns the values in dB scale. When *mode* is 'density',
6670-
this is dB power (10 * log10). Otherwise this is dB amplitude
6669+
'dB' returns the values in dB scale, i.e., the dB amplitude
66716670
(20 * log10). 'default' is 'linear'.
66726671
66736672
Fc : integer

‎lib/matplotlib/mlab.py

Copy file name to clipboardExpand all lines: lib/matplotlib/mlab.py
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -727,12 +727,12 @@ def _spectral_helper(x, y=None, NFFT=None, Fs=None, detrend_func=None,
727727
elif mode == 'psd':
728728
result = np.conj(result) * result
729729
elif mode == 'magnitude':
730-
result = np.abs(result)
730+
result = np.abs(result) / np.abs(windowVals).sum()
731731
elif mode == 'angle' or mode == 'phase':
732732
# we unwrap the phase later to handle the onesided vs. twosided case
733733
result = np.angle(result)
734734
elif mode == 'complex':
735-
pass
735+
result /= np.abs(windowVals).sum()
736736

737737
if mode == 'psd':
738738

Loading
Loading
Loading
Loading

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.