From cebd3d7b44e678562175d8f144cb7d07b88f6e3b Mon Sep 17 00:00:00 2001 From: Julian Chen Date: Wed, 1 Feb 2023 11:37:18 +0800 Subject: [PATCH 1/5] FIX: scaling factor for window with negative value Simply drop the `np.abs()` on window to fix the wrong scaling factor for window with negative value. For more detail refer to https://github.com/matplotlib/matplotlib/issues/24821 **Caution**: With this fix, the behavior would change for window with complex value. With `np.abs()` on window, it seems can handle complex value, but I don't think it's the right way to do it. As it can't fall back to real value case for complex value with zero imaginary part and negative real part (for example -1 + 0j). Also, I didn't understand the need for complex window, so here I simply ignore the complex case. And this is consistent with the implementation of [scipy](https://github.com/scipy/scipy/blob/d9f75db82fdffef06187c9d8d2f0f5b36c7a791b/scipy/signal/_spectral_py.py#L1854-L1859). --- lib/matplotlib/mlab.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/matplotlib/mlab.py b/lib/matplotlib/mlab.py index 3552904c3d74..efa2f84cae4b 100644 --- a/lib/matplotlib/mlab.py +++ b/lib/matplotlib/mlab.py @@ -395,12 +395,12 @@ 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) / window.sum() elif mode == 'angle' or mode == 'phase': # we unwrap the phase later to handle the onesided vs. twosided case result = np.angle(result) elif mode == 'complex': - result /= np.abs(window).sum() + result /= window.sum() if mode == 'psd': @@ -424,10 +424,10 @@ def _spectral_helper(x, y=None, NFFT=None, Fs=None, detrend_func=None, result /= Fs # Scale the spectrum by the norm of the window to compensate for # windowing loss; see Bendat & Piersol Sec 11.5.2. - result /= (np.abs(window)**2).sum() + result /= (window**2).sum() else: # In this case, preserve power in the segment, not amplitude - result /= np.abs(window).sum()**2 + result /= window.sum()**2 t = np.arange(NFFT/2, len(x) - NFFT/2 + 1, NFFT - noverlap)/Fs From b2c8f8845ce52850b37de561e55870801dd5764f Mon Sep 17 00:00:00 2001 From: Julian Chen Date: Wed, 1 Feb 2023 16:36:52 +0800 Subject: [PATCH 2/5] Test function for scale factor of flattop window Add new test function for scale factor of flattop window. Also remove the unnecessary `np.abs()` on window in other functions. --- lib/matplotlib/tests/test_mlab.py | 42 +++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/tests/test_mlab.py b/lib/matplotlib/tests/test_mlab.py index 86beb5c8c803..267d19d9a6ca 100644 --- a/lib/matplotlib/tests/test_mlab.py +++ b/lib/matplotlib/tests/test_mlab.py @@ -615,7 +615,7 @@ def test_psd_window_hanning(self): noverlap=0, sides=self.sides, window=mlab.window_none) - spec_c *= len(ycontrol1)/(np.abs(windowVals)**2).sum() + spec_c *= len(ycontrol1)/(windowVals**2).sum() assert_array_equal(fsp_g, fsp_c) assert_array_equal(fsp_b, fsp_c) assert_allclose(spec_g, spec_c, atol=1e-08) @@ -662,7 +662,7 @@ def test_psd_window_hanning_detrend_linear(self): noverlap=0, sides=self.sides, window=mlab.window_none) - spec_c *= len(ycontrol1)/(np.abs(windowVals)**2).sum() + spec_c *= len(ycontrol1)/(windowVals**2).sum() assert_array_equal(fsp_g, fsp_c) assert_array_equal(fsp_b, fsp_c) assert_allclose(spec_g, spec_c, atol=1e-08) @@ -670,6 +670,44 @@ def test_psd_window_hanning_detrend_linear(self): with pytest.raises(AssertionError): assert_allclose(spec_b, spec_c, atol=1e-08) + def test_psd_window_flattop(self): + # flattop window + # adaption from https://github.com/scipy/scipy/blob/v1.10.0/scipy/signal/windows/_windows.py#L562-L622 + if self.NFFT_density_real <=1: + win = np.ones(self.NFFT_density_real) + else: + a = [0.21557895, 0.41663158, 0.277263158, 0.083578947, 0.006947368] + fac = np.linspace(-np.pi, np.pi, self.NFFT_density_real) + win = np.zeros(self.NFFT_density_real) + for k in range(len(a)): + win += a[k] * np.cos(k * fac) + + spec, fsp = mlab.psd(x=self.y, + NFFT=self.NFFT_density, + Fs=self.Fs, + noverlap=0, + sides=self.sides, + window=win, + scale_by_freq=False) + spec_a, fsp_a = mlab.psd(x=self.y, + NFFT=self.NFFT_density, + Fs=self.Fs, + noverlap=0, + sides=self.sides, + window=win) + spec_b, fsp_b = mlab.psd(x=self.y * win, + NFFT=self.NFFT_density, + Fs=self.Fs, + noverlap=0, + sides=self.sides, + window=mlab.window_none) + assert_allclose(spec*win.sum()**2, + spec_a*self.Fs*(win**2).sum(), + atol=1e-08) + assert_allclose(spec*win.sum()**2, + spec_b*self.Fs*self.NFFT_density, + atol=1e-08) + def test_psd_windowarray(self): freqs = self.freqs_density spec, fsp = mlab.psd(x=self.y, From 76e53c11fcb73dcdbf22887e19fb30483da1cbff Mon Sep 17 00:00:00 2001 From: Julian Chen Date: Wed, 1 Feb 2023 17:20:26 +0800 Subject: [PATCH 3/5] fix bug in `test_psd_window_flattop` --- lib/matplotlib/tests/test_mlab.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/matplotlib/tests/test_mlab.py b/lib/matplotlib/tests/test_mlab.py index 267d19d9a6ca..7def4f4163e7 100644 --- a/lib/matplotlib/tests/test_mlab.py +++ b/lib/matplotlib/tests/test_mlab.py @@ -673,7 +673,7 @@ def test_psd_window_hanning_detrend_linear(self): def test_psd_window_flattop(self): # flattop window # adaption from https://github.com/scipy/scipy/blob/v1.10.0/scipy/signal/windows/_windows.py#L562-L622 - if self.NFFT_density_real <=1: + if self.NFFT_density_real <= 1: win = np.ones(self.NFFT_density_real) else: a = [0.21557895, 0.41663158, 0.277263158, 0.083578947, 0.006947368] @@ -695,18 +695,18 @@ def test_psd_window_flattop(self): noverlap=0, sides=self.sides, window=win) - spec_b, fsp_b = mlab.psd(x=self.y * win, - NFFT=self.NFFT_density, - Fs=self.Fs, - noverlap=0, - sides=self.sides, - window=mlab.window_none) + # spec_b, fsp_b = mlab.psd(x=self.y * win, + # NFFT=self.NFFT_density, + # Fs=self.Fs, + # noverlap=0, + # sides=self.sides, + # window=mlab.window_none) assert_allclose(spec*win.sum()**2, spec_a*self.Fs*(win**2).sum(), atol=1e-08) - assert_allclose(spec*win.sum()**2, - spec_b*self.Fs*self.NFFT_density, - atol=1e-08) + # assert_allclose(spec*win.sum()**2, + # spec_b*self.Fs*self.NFFT_density, + # atol=1e-08) def test_psd_windowarray(self): freqs = self.freqs_density From 456c4cf0f77752a7dbbd2b56108010e95f105d49 Mon Sep 17 00:00:00 2001 From: Julian Chen Date: Thu, 2 Feb 2023 14:10:28 +0800 Subject: [PATCH 4/5] update code formatting for `test_psd_window_flattop` --- lib/matplotlib/tests/test_mlab.py | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/lib/matplotlib/tests/test_mlab.py b/lib/matplotlib/tests/test_mlab.py index 7def4f4163e7..1cf468e2baae 100644 --- a/lib/matplotlib/tests/test_mlab.py +++ b/lib/matplotlib/tests/test_mlab.py @@ -672,15 +672,13 @@ def test_psd_window_hanning_detrend_linear(self): def test_psd_window_flattop(self): # flattop window - # adaption from https://github.com/scipy/scipy/blob/v1.10.0/scipy/signal/windows/_windows.py#L562-L622 - if self.NFFT_density_real <= 1: - win = np.ones(self.NFFT_density_real) - else: - a = [0.21557895, 0.41663158, 0.277263158, 0.083578947, 0.006947368] - fac = np.linspace(-np.pi, np.pi, self.NFFT_density_real) - win = np.zeros(self.NFFT_density_real) - for k in range(len(a)): - win += a[k] * np.cos(k * fac) + # adaption from https://github.com/scipy/scipy/blob\ + # /v1.10.0/scipy/signal/windows/_windows.py#L562-L622 + a = [0.21557895, 0.41663158, 0.277263158, 0.083578947, 0.006947368] + fac = np.linspace(-np.pi, np.pi, self.NFFT_density_real) + win = np.zeros(self.NFFT_density_real) + for k in range(len(a)): + win += a[k] * np.cos(k * fac) spec, fsp = mlab.psd(x=self.y, NFFT=self.NFFT_density, @@ -695,18 +693,10 @@ def test_psd_window_flattop(self): noverlap=0, sides=self.sides, window=win) - # spec_b, fsp_b = mlab.psd(x=self.y * win, - # NFFT=self.NFFT_density, - # Fs=self.Fs, - # noverlap=0, - # sides=self.sides, - # window=mlab.window_none) assert_allclose(spec*win.sum()**2, spec_a*self.Fs*(win**2).sum(), atol=1e-08) - # assert_allclose(spec*win.sum()**2, - # spec_b*self.Fs*self.NFFT_density, - # atol=1e-08) + def test_psd_windowarray(self): freqs = self.freqs_density From 0a9e63209ea7c30e9d23ea64e6284ae9aa253198 Mon Sep 17 00:00:00 2001 From: Julian Chen Date: Tue, 7 Feb 2023 16:40:55 +0800 Subject: [PATCH 5/5] code formatting: remove extra blank line --- lib/matplotlib/tests/test_mlab.py | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/matplotlib/tests/test_mlab.py b/lib/matplotlib/tests/test_mlab.py index 1cf468e2baae..9cd1b44cc1e2 100644 --- a/lib/matplotlib/tests/test_mlab.py +++ b/lib/matplotlib/tests/test_mlab.py @@ -697,7 +697,6 @@ def test_psd_window_flattop(self): spec_a*self.Fs*(win**2).sum(), atol=1e-08) - def test_psd_windowarray(self): freqs = self.freqs_density spec, fsp = mlab.psd(x=self.y, pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy