1import pickle
2
3import numpy as np
4from numpy import array
5from numpy.testing import (assert_array_almost_equal, assert_array_equal,
6                           assert_allclose,
7                           assert_equal, assert_, assert_array_less,
8                           suppress_warnings)
9from pytest import raises as assert_raises
10
11from scipy.fft import fft
12from scipy.signal import windows, get_window, resample, hann as dep_hann
13
14
15window_funcs = [
16    ('boxcar', ()),
17    ('triang', ()),
18    ('parzen', ()),
19    ('bohman', ()),
20    ('blackman', ()),
21    ('nuttall', ()),
22    ('blackmanharris', ()),
23    ('flattop', ()),
24    ('bartlett', ()),
25    ('hanning', ()),
26    ('barthann', ()),
27    ('hamming', ()),
28    ('kaiser', (1,)),
29    ('dpss', (2,)),
30    ('gaussian', (0.5,)),
31    ('general_gaussian', (1.5, 2)),
32    ('chebwin', (1,)),
33    ('cosine', ()),
34    ('hann', ()),
35    ('exponential', ()),
36    ('taylor', ()),
37    ('tukey', (0.5,)),
38    ]
39
40
41class TestBartHann:
42
43    def test_basic(self):
44        assert_allclose(windows.barthann(6, sym=True),
45                        [0, 0.35857354213752, 0.8794264578624801,
46                         0.8794264578624801, 0.3585735421375199, 0])
47        assert_allclose(windows.barthann(7),
48                        [0, 0.27, 0.73, 1.0, 0.73, 0.27, 0])
49        assert_allclose(windows.barthann(6, False),
50                        [0, 0.27, 0.73, 1.0, 0.73, 0.27])
51
52
53class TestBartlett:
54
55    def test_basic(self):
56        assert_allclose(windows.bartlett(6), [0, 0.4, 0.8, 0.8, 0.4, 0])
57        assert_allclose(windows.bartlett(7), [0, 1/3, 2/3, 1.0, 2/3, 1/3, 0])
58        assert_allclose(windows.bartlett(6, False),
59                        [0, 1/3, 2/3, 1.0, 2/3, 1/3])
60
61
62class TestBlackman:
63
64    def test_basic(self):
65        assert_allclose(windows.blackman(6, sym=False),
66                        [0, 0.13, 0.63, 1.0, 0.63, 0.13], atol=1e-14)
67        assert_allclose(windows.blackman(7, sym=False),
68                        [0, 0.09045342435412804, 0.4591829575459636,
69                         0.9203636180999081, 0.9203636180999081,
70                         0.4591829575459636, 0.09045342435412804], atol=1e-8)
71        assert_allclose(windows.blackman(6),
72                        [0, 0.2007701432625305, 0.8492298567374694,
73                         0.8492298567374694, 0.2007701432625305, 0],
74                        atol=1e-14)
75        assert_allclose(windows.blackman(7, True),
76                        [0, 0.13, 0.63, 1.0, 0.63, 0.13, 0], atol=1e-14)
77
78
79class TestBlackmanHarris:
80
81    def test_basic(self):
82        assert_allclose(windows.blackmanharris(6, False),
83                        [6.0e-05, 0.055645, 0.520575, 1.0, 0.520575, 0.055645])
84        assert_allclose(windows.blackmanharris(7, sym=False),
85                        [6.0e-05, 0.03339172347815117, 0.332833504298565,
86                         0.8893697722232837, 0.8893697722232838,
87                         0.3328335042985652, 0.03339172347815122])
88        assert_allclose(windows.blackmanharris(6),
89                        [6.0e-05, 0.1030114893456638, 0.7938335106543362,
90                         0.7938335106543364, 0.1030114893456638, 6.0e-05])
91        assert_allclose(windows.blackmanharris(7, sym=True),
92                        [6.0e-05, 0.055645, 0.520575, 1.0, 0.520575, 0.055645,
93                         6.0e-05])
94
95
96class TestTaylor:
97
98    def test_normalized(self):
99        """Tests windows of small length that are normalized to 1. See the
100        documentation for the Taylor window for more information on
101        normalization.
102        """
103        assert_allclose(windows.taylor(1, 2, 15), 1.0)
104        assert_allclose(
105            windows.taylor(5, 2, 15),
106            np.array([0.75803341, 0.90757699, 1.0, 0.90757699, 0.75803341])
107        )
108        assert_allclose(
109            windows.taylor(6, 2, 15),
110            np.array([
111                0.7504082, 0.86624416, 0.98208011, 0.98208011, 0.86624416,
112                0.7504082
113            ])
114        )
115
116    def test_non_normalized(self):
117        """Test windows of small length that are not normalized to 1. See
118        the documentation for the Taylor window for more information on
119        normalization.
120        """
121        assert_allclose(
122            windows.taylor(5, 2, 15, norm=False),
123            np.array([
124                0.87508054, 1.04771499, 1.15440894, 1.04771499, 0.87508054
125            ])
126        )
127        assert_allclose(
128            windows.taylor(6, 2, 15, norm=False),
129            np.array([
130                0.86627793, 1.0, 1.13372207, 1.13372207, 1.0, 0.86627793
131            ])
132        )
133
134    def test_correctness(self):
135        """This test ensures the correctness of the implemented Taylor
136        Windowing function. A Taylor Window of 1024 points is created, its FFT
137        is taken, and the Peak Sidelobe Level (PSLL) and 3dB and 18dB bandwidth
138        are found and checked.
139
140        A publication from Sandia National Laboratories was used as reference
141        for the correctness values [1]_.
142
143        References
144        -----
145        .. [1] Armin Doerry, "Catalog of Window Taper Functions for
146               Sidelobe Control", 2017.
147               https://www.researchgate.net/profile/Armin_Doerry/publication/316281181_Catalog_of_Window_Taper_Functions_for_Sidelobe_Control/links/58f92cb2a6fdccb121c9d54d/Catalog-of-Window-Taper-Functions-for-Sidelobe-Control.pdf
148        """
149        M_win = 1024
150        N_fft = 131072
151        # Set norm=False for correctness as the values obtained from the
152        # scientific publication do not normalize the values. Normalizing
153        # changes the sidelobe level from the desired value.
154        w = windows.taylor(M_win, nbar=4, sll=35, norm=False, sym=False)
155        f = fft(w, N_fft)
156        spec = 20 * np.log10(np.abs(f / np.amax(f)))
157
158        first_zero = np.argmax(np.diff(spec) > 0)
159
160        PSLL = np.amax(spec[first_zero:-first_zero])
161
162        BW_3dB = 2*np.argmax(spec <= -3.0102999566398121) / N_fft * M_win
163        BW_18dB = 2*np.argmax(spec <= -18.061799739838872) / N_fft * M_win
164
165        assert_allclose(PSLL, -35.1672, atol=1)
166        assert_allclose(BW_3dB, 1.1822, atol=0.1)
167        assert_allclose(BW_18dB, 2.6112, atol=0.1)
168
169
170class TestBohman:
171
172    def test_basic(self):
173        assert_allclose(windows.bohman(6),
174                        [0, 0.1791238937062839, 0.8343114522576858,
175                         0.8343114522576858, 0.1791238937062838, 0])
176        assert_allclose(windows.bohman(7, sym=True),
177                        [0, 0.1089977810442293, 0.6089977810442293, 1.0,
178                         0.6089977810442295, 0.1089977810442293, 0])
179        assert_allclose(windows.bohman(6, False),
180                        [0, 0.1089977810442293, 0.6089977810442293, 1.0,
181                         0.6089977810442295, 0.1089977810442293])
182
183
184class TestBoxcar:
185
186    def test_basic(self):
187        assert_allclose(windows.boxcar(6), [1, 1, 1, 1, 1, 1])
188        assert_allclose(windows.boxcar(7), [1, 1, 1, 1, 1, 1, 1])
189        assert_allclose(windows.boxcar(6, False), [1, 1, 1, 1, 1, 1])
190
191
192cheb_odd_true = array([0.200938, 0.107729, 0.134941, 0.165348,
193                       0.198891, 0.235450, 0.274846, 0.316836,
194                       0.361119, 0.407338, 0.455079, 0.503883,
195                       0.553248, 0.602637, 0.651489, 0.699227,
196                       0.745266, 0.789028, 0.829947, 0.867485,
197                       0.901138, 0.930448, 0.955010, 0.974482,
198                       0.988591, 0.997138, 1.000000, 0.997138,
199                       0.988591, 0.974482, 0.955010, 0.930448,
200                       0.901138, 0.867485, 0.829947, 0.789028,
201                       0.745266, 0.699227, 0.651489, 0.602637,
202                       0.553248, 0.503883, 0.455079, 0.407338,
203                       0.361119, 0.316836, 0.274846, 0.235450,
204                       0.198891, 0.165348, 0.134941, 0.107729,
205                       0.200938])
206
207cheb_even_true = array([0.203894, 0.107279, 0.133904,
208                        0.163608, 0.196338, 0.231986,
209                        0.270385, 0.311313, 0.354493,
210                        0.399594, 0.446233, 0.493983,
211                        0.542378, 0.590916, 0.639071,
212                        0.686302, 0.732055, 0.775783,
213                        0.816944, 0.855021, 0.889525,
214                        0.920006, 0.946060, 0.967339,
215                        0.983557, 0.994494, 1.000000,
216                        1.000000, 0.994494, 0.983557,
217                        0.967339, 0.946060, 0.920006,
218                        0.889525, 0.855021, 0.816944,
219                        0.775783, 0.732055, 0.686302,
220                        0.639071, 0.590916, 0.542378,
221                        0.493983, 0.446233, 0.399594,
222                        0.354493, 0.311313, 0.270385,
223                        0.231986, 0.196338, 0.163608,
224                        0.133904, 0.107279, 0.203894])
225
226
227class TestChebWin:
228
229    def test_basic(self):
230        with suppress_warnings() as sup:
231            sup.filter(UserWarning, "This window is not suitable")
232            assert_allclose(windows.chebwin(6, 100),
233                            [0.1046401879356917, 0.5075781475823447, 1.0, 1.0,
234                             0.5075781475823447, 0.1046401879356917])
235            assert_allclose(windows.chebwin(7, 100),
236                            [0.05650405062850233, 0.316608530648474,
237                             0.7601208123539079, 1.0, 0.7601208123539079,
238                             0.316608530648474, 0.05650405062850233])
239            assert_allclose(windows.chebwin(6, 10),
240                            [1.0, 0.6071201674458373, 0.6808391469897297,
241                             0.6808391469897297, 0.6071201674458373, 1.0])
242            assert_allclose(windows.chebwin(7, 10),
243                            [1.0, 0.5190521247588651, 0.5864059018130382,
244                             0.6101519801307441, 0.5864059018130382,
245                             0.5190521247588651, 1.0])
246            assert_allclose(windows.chebwin(6, 10, False),
247                            [1.0, 0.5190521247588651, 0.5864059018130382,
248                             0.6101519801307441, 0.5864059018130382,
249                             0.5190521247588651])
250
251    def test_cheb_odd_high_attenuation(self):
252        with suppress_warnings() as sup:
253            sup.filter(UserWarning, "This window is not suitable")
254            cheb_odd = windows.chebwin(53, at=-40)
255        assert_array_almost_equal(cheb_odd, cheb_odd_true, decimal=4)
256
257    def test_cheb_even_high_attenuation(self):
258        with suppress_warnings() as sup:
259            sup.filter(UserWarning, "This window is not suitable")
260            cheb_even = windows.chebwin(54, at=40)
261        assert_array_almost_equal(cheb_even, cheb_even_true, decimal=4)
262
263    def test_cheb_odd_low_attenuation(self):
264        cheb_odd_low_at_true = array([1.000000, 0.519052, 0.586405,
265                                      0.610151, 0.586405, 0.519052,
266                                      1.000000])
267        with suppress_warnings() as sup:
268            sup.filter(UserWarning, "This window is not suitable")
269            cheb_odd = windows.chebwin(7, at=10)
270        assert_array_almost_equal(cheb_odd, cheb_odd_low_at_true, decimal=4)
271
272    def test_cheb_even_low_attenuation(self):
273        cheb_even_low_at_true = array([1.000000, 0.451924, 0.51027,
274                                       0.541338, 0.541338, 0.51027,
275                                       0.451924, 1.000000])
276        with suppress_warnings() as sup:
277            sup.filter(UserWarning, "This window is not suitable")
278            cheb_even = windows.chebwin(8, at=-10)
279        assert_array_almost_equal(cheb_even, cheb_even_low_at_true, decimal=4)
280
281
282exponential_data = {
283    (4, None, 0.2, False):
284        array([4.53999297624848542e-05,
285               6.73794699908546700e-03, 1.00000000000000000e+00,
286               6.73794699908546700e-03]),
287    (4, None, 0.2, True): array([0.00055308437014783, 0.0820849986238988,
288                                 0.0820849986238988, 0.00055308437014783]),
289    (4, None, 1.0, False): array([0.1353352832366127, 0.36787944117144233, 1.,
290                                  0.36787944117144233]),
291    (4, None, 1.0, True): array([0.22313016014842982, 0.60653065971263342,
292                                 0.60653065971263342, 0.22313016014842982]),
293    (4, 2, 0.2, False):
294        array([4.53999297624848542e-05, 6.73794699908546700e-03,
295               1.00000000000000000e+00, 6.73794699908546700e-03]),
296    (4, 2, 0.2, True): None,
297    (4, 2, 1.0, False): array([0.1353352832366127, 0.36787944117144233, 1.,
298                               0.36787944117144233]),
299    (4, 2, 1.0, True): None,
300    (5, None, 0.2, True):
301        array([4.53999297624848542e-05,
302               6.73794699908546700e-03, 1.00000000000000000e+00,
303               6.73794699908546700e-03, 4.53999297624848542e-05]),
304    (5, None, 1.0, True): array([0.1353352832366127, 0.36787944117144233, 1.,
305                                 0.36787944117144233, 0.1353352832366127]),
306    (5, 2, 0.2, True): None,
307    (5, 2, 1.0, True): None
308}
309
310
311def test_exponential():
312    for k, v in exponential_data.items():
313        if v is None:
314            assert_raises(ValueError, windows.exponential, *k)
315        else:
316            win = windows.exponential(*k)
317            assert_allclose(win, v, rtol=1e-14)
318
319
320class TestFlatTop:
321
322    def test_basic(self):
323        assert_allclose(windows.flattop(6, sym=False),
324                        [-0.000421051, -0.051263156, 0.19821053, 1.0,
325                         0.19821053, -0.051263156])
326        assert_allclose(windows.flattop(7, sym=False),
327                        [-0.000421051, -0.03684078115492348,
328                         0.01070371671615342, 0.7808739149387698,
329                         0.7808739149387698, 0.01070371671615342,
330                         -0.03684078115492348])
331        assert_allclose(windows.flattop(6),
332                        [-0.000421051, -0.0677142520762119, 0.6068721525762117,
333                         0.6068721525762117, -0.0677142520762119,
334                         -0.000421051])
335        assert_allclose(windows.flattop(7, True),
336                        [-0.000421051, -0.051263156, 0.19821053, 1.0,
337                         0.19821053, -0.051263156, -0.000421051])
338
339
340class TestGaussian:
341
342    def test_basic(self):
343        assert_allclose(windows.gaussian(6, 1.0),
344                        [0.04393693362340742, 0.3246524673583497,
345                         0.8824969025845955, 0.8824969025845955,
346                         0.3246524673583497, 0.04393693362340742])
347        assert_allclose(windows.gaussian(7, 1.2),
348                        [0.04393693362340742, 0.2493522087772962,
349                         0.7066482778577162, 1.0, 0.7066482778577162,
350                         0.2493522087772962, 0.04393693362340742])
351        assert_allclose(windows.gaussian(7, 3),
352                        [0.6065306597126334, 0.8007374029168081,
353                         0.9459594689067654, 1.0, 0.9459594689067654,
354                         0.8007374029168081, 0.6065306597126334])
355        assert_allclose(windows.gaussian(6, 3, False),
356                        [0.6065306597126334, 0.8007374029168081,
357                         0.9459594689067654, 1.0, 0.9459594689067654,
358                         0.8007374029168081])
359
360
361class TestGeneralCosine:
362
363    def test_basic(self):
364        assert_allclose(windows.general_cosine(5, [0.5, 0.3, 0.2]),
365                        [0.4, 0.3, 1, 0.3, 0.4])
366        assert_allclose(windows.general_cosine(4, [0.5, 0.3, 0.2], sym=False),
367                        [0.4, 0.3, 1, 0.3])
368
369
370class TestGeneralHamming:
371
372    def test_basic(self):
373        assert_allclose(windows.general_hamming(5, 0.7),
374                        [0.4, 0.7, 1.0, 0.7, 0.4])
375        assert_allclose(windows.general_hamming(5, 0.75, sym=False),
376                        [0.5, 0.6727457514, 0.9522542486,
377                         0.9522542486, 0.6727457514])
378        assert_allclose(windows.general_hamming(6, 0.75, sym=True),
379                        [0.5, 0.6727457514, 0.9522542486,
380                        0.9522542486, 0.6727457514, 0.5])
381
382
383class TestHamming:
384
385    def test_basic(self):
386        assert_allclose(windows.hamming(6, False),
387                        [0.08, 0.31, 0.77, 1.0, 0.77, 0.31])
388        assert_allclose(windows.hamming(7, sym=False),
389                        [0.08, 0.2531946911449826, 0.6423596296199047,
390                         0.9544456792351128, 0.9544456792351128,
391                         0.6423596296199047, 0.2531946911449826])
392        assert_allclose(windows.hamming(6),
393                        [0.08, 0.3978521825875242, 0.9121478174124757,
394                         0.9121478174124757, 0.3978521825875242, 0.08])
395        assert_allclose(windows.hamming(7, sym=True),
396                        [0.08, 0.31, 0.77, 1.0, 0.77, 0.31, 0.08])
397
398
399class TestHann:
400
401    def test_basic(self):
402        assert_allclose(windows.hann(6, sym=False),
403                        [0, 0.25, 0.75, 1.0, 0.75, 0.25])
404        assert_allclose(windows.hann(7, sym=False),
405                        [0, 0.1882550990706332, 0.6112604669781572,
406                         0.9504844339512095, 0.9504844339512095,
407                         0.6112604669781572, 0.1882550990706332])
408        assert_allclose(windows.hann(6, True),
409                        [0, 0.3454915028125263, 0.9045084971874737,
410                         0.9045084971874737, 0.3454915028125263, 0])
411        assert_allclose(windows.hann(7),
412                        [0, 0.25, 0.75, 1.0, 0.75, 0.25, 0])
413
414
415class TestKaiser:
416
417    def test_basic(self):
418        assert_allclose(windows.kaiser(6, 0.5),
419                        [0.9403061933191572, 0.9782962393705389,
420                         0.9975765035372042, 0.9975765035372042,
421                         0.9782962393705389, 0.9403061933191572])
422        assert_allclose(windows.kaiser(7, 0.5),
423                        [0.9403061933191572, 0.9732402256999829,
424                         0.9932754654413773, 1.0, 0.9932754654413773,
425                         0.9732402256999829, 0.9403061933191572])
426        assert_allclose(windows.kaiser(6, 2.7),
427                        [0.2603047507678832, 0.6648106293528054,
428                         0.9582099802511439, 0.9582099802511439,
429                         0.6648106293528054, 0.2603047507678832])
430        assert_allclose(windows.kaiser(7, 2.7),
431                        [0.2603047507678832, 0.5985765418119844,
432                         0.8868495172060835, 1.0, 0.8868495172060835,
433                         0.5985765418119844, 0.2603047507678832])
434        assert_allclose(windows.kaiser(6, 2.7, False),
435                        [0.2603047507678832, 0.5985765418119844,
436                         0.8868495172060835, 1.0, 0.8868495172060835,
437                         0.5985765418119844])
438
439
440class TestNuttall:
441
442    def test_basic(self):
443        assert_allclose(windows.nuttall(6, sym=False),
444                        [0.0003628, 0.0613345, 0.5292298, 1.0, 0.5292298,
445                         0.0613345])
446        assert_allclose(windows.nuttall(7, sym=False),
447                        [0.0003628, 0.03777576895352025, 0.3427276199688195,
448                         0.8918518610776603, 0.8918518610776603,
449                         0.3427276199688196, 0.0377757689535203])
450        assert_allclose(windows.nuttall(6),
451                        [0.0003628, 0.1105152530498718, 0.7982580969501282,
452                         0.7982580969501283, 0.1105152530498719, 0.0003628])
453        assert_allclose(windows.nuttall(7, True),
454                        [0.0003628, 0.0613345, 0.5292298, 1.0, 0.5292298,
455                         0.0613345, 0.0003628])
456
457
458class TestParzen:
459
460    def test_basic(self):
461        assert_allclose(windows.parzen(6),
462                        [0.009259259259259254, 0.25, 0.8611111111111112,
463                         0.8611111111111112, 0.25, 0.009259259259259254])
464        assert_allclose(windows.parzen(7, sym=True),
465                        [0.00583090379008747, 0.1574344023323616,
466                         0.6501457725947521, 1.0, 0.6501457725947521,
467                         0.1574344023323616, 0.00583090379008747])
468        assert_allclose(windows.parzen(6, False),
469                        [0.00583090379008747, 0.1574344023323616,
470                         0.6501457725947521, 1.0, 0.6501457725947521,
471                         0.1574344023323616])
472
473
474class TestTriang:
475
476    def test_basic(self):
477
478        assert_allclose(windows.triang(6, True),
479                        [1/6, 1/2, 5/6, 5/6, 1/2, 1/6])
480        assert_allclose(windows.triang(7),
481                        [1/4, 1/2, 3/4, 1, 3/4, 1/2, 1/4])
482        assert_allclose(windows.triang(6, sym=False),
483                        [1/4, 1/2, 3/4, 1, 3/4, 1/2])
484
485
486tukey_data = {
487    (4, 0.5, True): array([0.0, 1.0, 1.0, 0.0]),
488    (4, 0.9, True): array([0.0, 0.84312081893436686,
489                           0.84312081893436686, 0.0]),
490    (4, 1.0, True): array([0.0, 0.75, 0.75, 0.0]),
491    (4, 0.5, False): array([0.0, 1.0, 1.0, 1.0]),
492    (4, 0.9, False): array([0.0, 0.58682408883346526,
493                            1.0, 0.58682408883346526]),
494    (4, 1.0, False): array([0.0, 0.5, 1.0, 0.5]),
495    (5, 0.0, True): array([1.0, 1.0, 1.0, 1.0, 1.0]),
496    (5, 0.8, True): array([0.0, 0.69134171618254492,
497                           1.0, 0.69134171618254492, 0.0]),
498    (5, 1.0, True): array([0.0, 0.5, 1.0, 0.5, 0.0]),
499
500    (6, 0): [1, 1, 1, 1, 1, 1],
501    (7, 0): [1, 1, 1, 1, 1, 1, 1],
502    (6, .25): [0, 1, 1, 1, 1, 0],
503    (7, .25): [0, 1, 1, 1, 1, 1, 0],
504    (6,): [0, 0.9045084971874737, 1.0, 1.0, 0.9045084971874735, 0],
505    (7,): [0, 0.75, 1.0, 1.0, 1.0, 0.75, 0],
506    (6, .75): [0, 0.5522642316338269, 1.0, 1.0, 0.5522642316338267, 0],
507    (7, .75): [0, 0.4131759111665348, 0.9698463103929542, 1.0,
508               0.9698463103929542, 0.4131759111665347, 0],
509    (6, 1): [0, 0.3454915028125263, 0.9045084971874737, 0.9045084971874737,
510             0.3454915028125263, 0],
511    (7, 1): [0, 0.25, 0.75, 1.0, 0.75, 0.25, 0],
512}
513
514
515class TestTukey:
516
517    def test_basic(self):
518        # Test against hardcoded data
519        for k, v in tukey_data.items():
520            if v is None:
521                assert_raises(ValueError, windows.tukey, *k)
522            else:
523                win = windows.tukey(*k)
524                assert_allclose(win, v, rtol=1e-14)
525
526    def test_extremes(self):
527        # Test extremes of alpha correspond to boxcar and hann
528        tuk0 = windows.tukey(100, 0)
529        box0 = windows.boxcar(100)
530        assert_array_almost_equal(tuk0, box0)
531
532        tuk1 = windows.tukey(100, 1)
533        han1 = windows.hann(100)
534        assert_array_almost_equal(tuk1, han1)
535
536
537dpss_data = {
538    # All values from MATLAB:
539    # * taper[1] of (3, 1.4, 3) sign-flipped
540    # * taper[3] of (5, 1.5, 5) sign-flipped
541    (4, 0.1, 2): ([[0.497943898, 0.502047681, 0.502047681, 0.497943898], [0.670487993, 0.224601537, -0.224601537, -0.670487993]], [0.197961815, 0.002035474]),  # noqa
542    (3, 1.4, 3): ([[0.410233151, 0.814504464, 0.410233151], [0.707106781, 0.0, -0.707106781], [0.575941629, -0.580157287, 0.575941629]], [0.999998093, 0.998067480, 0.801934426]),  # noqa
543    (5, 1.5, 5): ([[0.1745071052, 0.4956749177, 0.669109327, 0.495674917, 0.174507105], [0.4399493348, 0.553574369, 0.0, -0.553574369, -0.439949334], [0.631452756, 0.073280238, -0.437943884, 0.073280238, 0.631452756], [0.553574369, -0.439949334, 0.0, 0.439949334, -0.553574369], [0.266110290, -0.498935248, 0.600414741, -0.498935248, 0.266110290147157]], [0.999728571, 0.983706916, 0.768457889, 0.234159338, 0.013947282907567]),  # noqa: E501
544    (100, 2, 4): ([[0.0030914414, 0.0041266922, 0.005315076, 0.006665149, 0.008184854, 0.0098814158, 0.011761239, 0.013829809, 0.016091597, 0.018549973, 0.02120712, 0.02406396, 0.027120092, 0.030373728, 0.033821651, 0.037459181, 0.041280145, 0.045276872, 0.049440192, 0.053759447, 0.058222524, 0.062815894, 0.067524661, 0.072332638, 0.077222418, 0.082175473, 0.087172252, 0.092192299, 0.097214376, 0.1022166, 0.10717657, 0.11207154, 0.11687856, 0.12157463, 0.12613686, 0.13054266, 0.13476986, 0.13879691, 0.14260302, 0.14616832, 0.14947401, 0.1525025, 0.15523755, 0.15766438, 0.15976981, 0.16154233, 0.16297223, 0.16405162, 0.16477455, 0.16513702, 0.16513702, 0.16477455, 0.16405162, 0.16297223, 0.16154233, 0.15976981, 0.15766438, 0.15523755, 0.1525025, 0.14947401, 0.14616832, 0.14260302, 0.13879691, 0.13476986, 0.13054266, 0.12613686, 0.12157463, 0.11687856, 0.11207154, 0.10717657, 0.1022166, 0.097214376, 0.092192299, 0.087172252, 0.082175473, 0.077222418, 0.072332638, 0.067524661, 0.062815894, 0.058222524, 0.053759447, 0.049440192, 0.045276872, 0.041280145, 0.037459181, 0.033821651, 0.030373728, 0.027120092, 0.02406396, 0.02120712, 0.018549973, 0.016091597, 0.013829809, 0.011761239, 0.0098814158, 0.008184854, 0.006665149, 0.005315076, 0.0041266922, 0.0030914414], [0.018064449, 0.022040342, 0.026325013, 0.030905288, 0.035764398, 0.040881982, 0.046234148, 0.051793558, 0.057529559, 0.063408356, 0.069393216, 0.075444716, 0.081521022, 0.087578202, 0.093570567, 0.099451049, 0.10517159, 0.11068356, 0.11593818, 0.12088699, 0.12548227, 0.12967752, 0.1334279, 0.13669069, 0.13942569, 0.1415957, 0.14316686, 0.14410905, 0.14439626, 0.14400686, 0.14292389, 0.1411353, 0.13863416, 0.13541876, 0.13149274, 0.12686516, 0.12155045, 0.1155684, 0.10894403, 0.10170748, 0.093893752, 0.08554251, 0.076697768, 0.067407559, 0.057723559, 0.04770068, 0.037396627, 0.026871428, 0.016186944, 0.0054063557, -0.0054063557, -0.016186944, -0.026871428, -0.037396627, -0.04770068, -0.057723559, -0.067407559, -0.076697768, -0.08554251, -0.093893752, -0.10170748, -0.10894403, -0.1155684, -0.12155045, -0.12686516, -0.13149274, -0.13541876, -0.13863416, -0.1411353, -0.14292389, -0.14400686, -0.14439626, -0.14410905, -0.14316686, -0.1415957, -0.13942569, -0.13669069, -0.1334279, -0.12967752, -0.12548227, -0.12088699, -0.11593818, -0.11068356, -0.10517159, -0.099451049, -0.093570567, -0.087578202, -0.081521022, -0.075444716, -0.069393216, -0.063408356, -0.057529559, -0.051793558, -0.046234148, -0.040881982, -0.035764398, -0.030905288, -0.026325013, -0.022040342, -0.018064449], [0.064817553, 0.072567801, 0.080292992, 0.087918235, 0.095367076, 0.10256232, 0.10942687, 0.1158846, 0.12186124, 0.12728523, 0.13208858, 0.13620771, 0.13958427, 0.14216587, 0.14390678, 0.14476863, 0.1447209, 0.14374148, 0.14181704, 0.13894336, 0.13512554, 0.13037812, 0.1247251, 0.11819984, 0.11084487, 0.10271159, 0.093859853, 0.084357497, 0.074279719, 0.063708406, 0.052731374, 0.041441525, 0.029935953, 0.018314987, 0.0066811877, -0.0048616765, -0.016209689, -0.027259848, -0.037911124, -0.048065512, -0.05762905, -0.066512804, -0.0746338, -0.081915903, -0.088290621, -0.09369783, -0.098086416, -0.10141482, -0.10365146, -0.10477512, -0.10477512, -0.10365146, -0.10141482, -0.098086416, -0.09369783, -0.088290621, -0.081915903, -0.0746338, -0.066512804, -0.05762905, -0.048065512, -0.037911124, -0.027259848, -0.016209689, -0.0048616765, 0.0066811877, 0.018314987, 0.029935953, 0.041441525, 0.052731374, 0.063708406, 0.074279719, 0.084357497, 0.093859853, 0.10271159, 0.11084487, 0.11819984, 0.1247251, 0.13037812, 0.13512554, 0.13894336, 0.14181704, 0.14374148, 0.1447209, 0.14476863, 0.14390678, 0.14216587, 0.13958427, 0.13620771, 0.13208858, 0.12728523, 0.12186124, 0.1158846, 0.10942687, 0.10256232, 0.095367076, 0.087918235, 0.080292992, 0.072567801, 0.064817553], [0.14985551, 0.15512305, 0.15931467, 0.16236806, 0.16423291, 0.16487165, 0.16426009, 0.1623879, 0.1592589, 0.15489114, 0.14931693, 0.14258255, 0.13474785, 0.1258857, 0.11608124, 0.10543095, 0.094041635, 0.082029213, 0.069517411, 0.056636348, 0.043521028, 0.030309756, 0.017142511, 0.0041592774, -0.0085016282, -0.020705223, -0.032321494, -0.043226982, -0.053306291, -0.062453515, -0.070573544, -0.077583253, -0.083412547, -0.088005244, -0.091319802, -0.093329861, -0.094024602, -0.093408915, -0.091503383, -0.08834406, -0.08398207, -0.078483012, -0.071926192, -0.064403681, -0.056019215, -0.046886954, -0.037130106, -0.026879442, -0.016271713, -0.005448, 0.005448, 0.016271713, 0.026879442, 0.037130106, 0.046886954, 0.056019215, 0.064403681, 0.071926192, 0.078483012, 0.08398207, 0.08834406, 0.091503383, 0.093408915, 0.094024602, 0.093329861, 0.091319802, 0.088005244, 0.083412547, 0.077583253, 0.070573544, 0.062453515, 0.053306291, 0.043226982, 0.032321494, 0.020705223, 0.0085016282, -0.0041592774, -0.017142511, -0.030309756, -0.043521028, -0.056636348, -0.069517411, -0.082029213, -0.094041635, -0.10543095, -0.11608124, -0.1258857, -0.13474785, -0.14258255, -0.14931693, -0.15489114, -0.1592589, -0.1623879, -0.16426009, -0.16487165, -0.16423291, -0.16236806, -0.15931467, -0.15512305, -0.14985551]], [0.999943140, 0.997571533, 0.959465463, 0.721862496]),  # noqa: E501
545}
546
547
548class TestDPSS:
549
550    def test_basic(self):
551        # Test against hardcoded data
552        for k, v in dpss_data.items():
553            win, ratios = windows.dpss(*k, return_ratios=True)
554            assert_allclose(win, v[0], atol=1e-7, err_msg=k)
555            assert_allclose(ratios, v[1], rtol=1e-5, atol=1e-7, err_msg=k)
556
557    def test_unity(self):
558        # Test unity value handling (gh-2221)
559        for M in range(1, 21):
560            # corrected w/approximation (default)
561            win = windows.dpss(M, M / 2.1)
562            expected = M % 2  # one for odd, none for even
563            assert_equal(np.isclose(win, 1.).sum(), expected,
564                         err_msg='%s' % (win,))
565            # corrected w/subsample delay (slower)
566            win_sub = windows.dpss(M, M / 2.1, norm='subsample')
567            if M > 2:
568                # @M=2 the subsample doesn't do anything
569                assert_equal(np.isclose(win_sub, 1.).sum(), expected,
570                             err_msg='%s' % (win_sub,))
571                assert_allclose(win, win_sub, rtol=0.03)  # within 3%
572            # not the same, l2-norm
573            win_2 = windows.dpss(M, M / 2.1, norm=2)
574            expected = 1 if M == 1 else 0
575            assert_equal(np.isclose(win_2, 1.).sum(), expected,
576                         err_msg='%s' % (win_2,))
577
578    def test_extremes(self):
579        # Test extremes of alpha
580        lam = windows.dpss(31, 6, 4, return_ratios=True)[1]
581        assert_array_almost_equal(lam, 1.)
582        lam = windows.dpss(31, 7, 4, return_ratios=True)[1]
583        assert_array_almost_equal(lam, 1.)
584        lam = windows.dpss(31, 8, 4, return_ratios=True)[1]
585        assert_array_almost_equal(lam, 1.)
586
587    def test_degenerate(self):
588        # Test failures
589        assert_raises(ValueError, windows.dpss, 4, 1.5, -1)  # Bad Kmax
590        assert_raises(ValueError, windows.dpss, 4, 1.5, -5)
591        assert_raises(TypeError, windows.dpss, 4, 1.5, 1.1)
592        assert_raises(ValueError, windows.dpss, 3, 1.5, 3)  # NW must be < N/2.
593        assert_raises(ValueError, windows.dpss, 3, -1, 3)  # NW must be pos
594        assert_raises(ValueError, windows.dpss, 3, 0, 3)
595        assert_raises(ValueError, windows.dpss, -1, 1, 3)  # negative M
596
597
598class TestGetWindow:
599
600    def test_boxcar(self):
601        w = windows.get_window('boxcar', 12)
602        assert_array_equal(w, np.ones_like(w))
603
604        # window is a tuple of len 1
605        w = windows.get_window(('boxcar',), 16)
606        assert_array_equal(w, np.ones_like(w))
607
608    def test_cheb_odd(self):
609        with suppress_warnings() as sup:
610            sup.filter(UserWarning, "This window is not suitable")
611            w = windows.get_window(('chebwin', -40), 53, fftbins=False)
612        assert_array_almost_equal(w, cheb_odd_true, decimal=4)
613
614    def test_cheb_even(self):
615        with suppress_warnings() as sup:
616            sup.filter(UserWarning, "This window is not suitable")
617            w = windows.get_window(('chebwin', 40), 54, fftbins=False)
618        assert_array_almost_equal(w, cheb_even_true, decimal=4)
619
620    def test_dpss(self):
621        win1 = windows.get_window(('dpss', 3), 64, fftbins=False)
622        win2 = windows.dpss(64, 3)
623        assert_array_almost_equal(win1, win2, decimal=4)
624
625    def test_kaiser_float(self):
626        win1 = windows.get_window(7.2, 64)
627        win2 = windows.kaiser(64, 7.2, False)
628        assert_allclose(win1, win2)
629
630    def test_invalid_inputs(self):
631        # Window is not a float, tuple, or string
632        assert_raises(ValueError, windows.get_window, set('hann'), 8)
633
634        # Unknown window type error
635        assert_raises(ValueError, windows.get_window, 'broken', 4)
636
637    def test_array_as_window(self):
638        # github issue 3603
639        osfactor = 128
640        sig = np.arange(128)
641
642        win = windows.get_window(('kaiser', 8.0), osfactor // 2)
643        with assert_raises(ValueError, match='must have the same length'):
644            resample(sig, len(sig) * osfactor, window=win)
645
646    def test_general_cosine(self):
647        assert_allclose(get_window(('general_cosine', [0.5, 0.3, 0.2]), 4),
648                        [0.4, 0.3, 1, 0.3])
649        assert_allclose(get_window(('general_cosine', [0.5, 0.3, 0.2]), 4,
650                                   fftbins=False),
651                        [0.4, 0.55, 0.55, 0.4])
652
653    def test_general_hamming(self):
654        assert_allclose(get_window(('general_hamming', 0.7), 5),
655                        [0.4, 0.6072949, 0.9427051, 0.9427051, 0.6072949])
656        assert_allclose(get_window(('general_hamming', 0.7), 5, fftbins=False),
657                        [0.4, 0.7, 1.0, 0.7, 0.4])
658
659
660def test_windowfunc_basics():
661    for window_name, params in window_funcs:
662        window = getattr(windows, window_name)
663        with suppress_warnings() as sup:
664            sup.filter(UserWarning, "This window is not suitable")
665            if window_name in ('hanning',):
666                sup.filter(DeprecationWarning)
667            # Check symmetry for odd and even lengths
668            w1 = window(8, *params, sym=True)
669            w2 = window(7, *params, sym=False)
670            assert_array_almost_equal(w1[:-1], w2)
671
672            w1 = window(9, *params, sym=True)
673            w2 = window(8, *params, sym=False)
674            assert_array_almost_equal(w1[:-1], w2)
675
676            # Check that functions run and output lengths are correct
677            assert_equal(len(window(6, *params, sym=True)), 6)
678            assert_equal(len(window(6, *params, sym=False)), 6)
679            assert_equal(len(window(7, *params, sym=True)), 7)
680            assert_equal(len(window(7, *params, sym=False)), 7)
681
682            # Check invalid lengths
683            assert_raises(ValueError, window, 5.5, *params)
684            assert_raises(ValueError, window, -7, *params)
685
686            # Check degenerate cases
687            assert_array_equal(window(0, *params, sym=True), [])
688            assert_array_equal(window(0, *params, sym=False), [])
689            assert_array_equal(window(1, *params, sym=True), [1])
690            assert_array_equal(window(1, *params, sym=False), [1])
691
692            # Check dtype
693            assert_(window(0, *params, sym=True).dtype == 'float')
694            assert_(window(0, *params, sym=False).dtype == 'float')
695            assert_(window(1, *params, sym=True).dtype == 'float')
696            assert_(window(1, *params, sym=False).dtype == 'float')
697            assert_(window(6, *params, sym=True).dtype == 'float')
698            assert_(window(6, *params, sym=False).dtype == 'float')
699
700            # Check normalization
701            assert_array_less(window(10, *params, sym=True), 1.01)
702            assert_array_less(window(10, *params, sym=False), 1.01)
703            assert_array_less(window(9, *params, sym=True), 1.01)
704            assert_array_less(window(9, *params, sym=False), 1.01)
705
706            # Check that DFT-even spectrum is purely real for odd and even
707            assert_allclose(fft(window(10, *params, sym=False)).imag,
708                            0, atol=1e-14)
709            assert_allclose(fft(window(11, *params, sym=False)).imag,
710                            0, atol=1e-14)
711
712
713def test_needs_params():
714    for winstr in ['kaiser', 'ksr', 'gaussian', 'gauss', 'gss',
715                   'general gaussian', 'general_gaussian',
716                   'general gauss', 'general_gauss', 'ggs',
717                   'dss', 'dpss', 'general cosine', 'general_cosine',
718                   'chebwin', 'cheb', 'general hamming', 'general_hamming',
719                   ]:
720        assert_raises(ValueError, get_window, winstr, 7)
721
722
723def test_not_needs_params():
724    for winstr in ['barthann',
725                   'bartlett',
726                   'blackman',
727                   'blackmanharris',
728                   'bohman',
729                   'boxcar',
730                   'cosine',
731                   'flattop',
732                   'hamming',
733                   'hanning',
734                   'nuttall',
735                   'parzen',
736                   'taylor',
737                   'exponential',
738                   'poisson',
739                   'tukey',
740                   'tuk',
741                   'triangle']:
742        win = get_window(winstr, 7)
743        assert_equal(len(win), 7)
744
745
746def test_deprecation():
747    if dep_hann.__doc__ is not None:  # can be None with `-OO` mode
748        assert_('signal.hann is deprecated' in dep_hann.__doc__)
749        assert_('deprecated' not in windows.hann.__doc__)
750
751
752def test_deprecated_pickleable():
753    dep_hann2 = pickle.loads(pickle.dumps(dep_hann))
754    assert_(dep_hann2 is dep_hann)
755