test_windows.py 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852
  1. import pickle
  2. import numpy as np
  3. from numpy import array
  4. from numpy.testing import (assert_array_almost_equal, assert_array_equal,
  5. assert_allclose,
  6. assert_equal, assert_, assert_array_less,
  7. suppress_warnings)
  8. from pytest import raises as assert_raises
  9. from scipy.fft import fft
  10. from scipy.signal import windows, get_window, resample, hann as dep_hann
  11. window_funcs = [
  12. ('boxcar', ()),
  13. ('triang', ()),
  14. ('parzen', ()),
  15. ('bohman', ()),
  16. ('blackman', ()),
  17. ('nuttall', ()),
  18. ('blackmanharris', ()),
  19. ('flattop', ()),
  20. ('bartlett', ()),
  21. ('barthann', ()),
  22. ('hamming', ()),
  23. ('kaiser', (1,)),
  24. ('dpss', (2,)),
  25. ('gaussian', (0.5,)),
  26. ('general_gaussian', (1.5, 2)),
  27. ('chebwin', (1,)),
  28. ('cosine', ()),
  29. ('hann', ()),
  30. ('exponential', ()),
  31. ('taylor', ()),
  32. ('tukey', (0.5,)),
  33. ('lanczos', ()),
  34. ]
  35. class TestBartHann:
  36. def test_basic(self):
  37. assert_allclose(windows.barthann(6, sym=True),
  38. [0, 0.35857354213752, 0.8794264578624801,
  39. 0.8794264578624801, 0.3585735421375199, 0])
  40. assert_allclose(windows.barthann(7),
  41. [0, 0.27, 0.73, 1.0, 0.73, 0.27, 0])
  42. assert_allclose(windows.barthann(6, False),
  43. [0, 0.27, 0.73, 1.0, 0.73, 0.27])
  44. class TestBartlett:
  45. def test_basic(self):
  46. assert_allclose(windows.bartlett(6), [0, 0.4, 0.8, 0.8, 0.4, 0])
  47. assert_allclose(windows.bartlett(7), [0, 1/3, 2/3, 1.0, 2/3, 1/3, 0])
  48. assert_allclose(windows.bartlett(6, False),
  49. [0, 1/3, 2/3, 1.0, 2/3, 1/3])
  50. class TestBlackman:
  51. def test_basic(self):
  52. assert_allclose(windows.blackman(6, sym=False),
  53. [0, 0.13, 0.63, 1.0, 0.63, 0.13], atol=1e-14)
  54. assert_allclose(windows.blackman(7, sym=False),
  55. [0, 0.09045342435412804, 0.4591829575459636,
  56. 0.9203636180999081, 0.9203636180999081,
  57. 0.4591829575459636, 0.09045342435412804], atol=1e-8)
  58. assert_allclose(windows.blackman(6),
  59. [0, 0.2007701432625305, 0.8492298567374694,
  60. 0.8492298567374694, 0.2007701432625305, 0],
  61. atol=1e-14)
  62. assert_allclose(windows.blackman(7, True),
  63. [0, 0.13, 0.63, 1.0, 0.63, 0.13, 0], atol=1e-14)
  64. class TestBlackmanHarris:
  65. def test_basic(self):
  66. assert_allclose(windows.blackmanharris(6, False),
  67. [6.0e-05, 0.055645, 0.520575, 1.0, 0.520575, 0.055645])
  68. assert_allclose(windows.blackmanharris(7, sym=False),
  69. [6.0e-05, 0.03339172347815117, 0.332833504298565,
  70. 0.8893697722232837, 0.8893697722232838,
  71. 0.3328335042985652, 0.03339172347815122])
  72. assert_allclose(windows.blackmanharris(6),
  73. [6.0e-05, 0.1030114893456638, 0.7938335106543362,
  74. 0.7938335106543364, 0.1030114893456638, 6.0e-05])
  75. assert_allclose(windows.blackmanharris(7, sym=True),
  76. [6.0e-05, 0.055645, 0.520575, 1.0, 0.520575, 0.055645,
  77. 6.0e-05])
  78. class TestTaylor:
  79. def test_normalized(self):
  80. """Tests windows of small length that are normalized to 1. See the
  81. documentation for the Taylor window for more information on
  82. normalization.
  83. """
  84. assert_allclose(windows.taylor(1, 2, 15), 1.0)
  85. assert_allclose(
  86. windows.taylor(5, 2, 15),
  87. np.array([0.75803341, 0.90757699, 1.0, 0.90757699, 0.75803341])
  88. )
  89. assert_allclose(
  90. windows.taylor(6, 2, 15),
  91. np.array([
  92. 0.7504082, 0.86624416, 0.98208011, 0.98208011, 0.86624416,
  93. 0.7504082
  94. ])
  95. )
  96. def test_non_normalized(self):
  97. """Test windows of small length that are not normalized to 1. See
  98. the documentation for the Taylor window for more information on
  99. normalization.
  100. """
  101. assert_allclose(
  102. windows.taylor(5, 2, 15, norm=False),
  103. np.array([
  104. 0.87508054, 1.04771499, 1.15440894, 1.04771499, 0.87508054
  105. ])
  106. )
  107. assert_allclose(
  108. windows.taylor(6, 2, 15, norm=False),
  109. np.array([
  110. 0.86627793, 1.0, 1.13372207, 1.13372207, 1.0, 0.86627793
  111. ])
  112. )
  113. def test_correctness(self):
  114. """This test ensures the correctness of the implemented Taylor
  115. Windowing function. A Taylor Window of 1024 points is created, its FFT
  116. is taken, and the Peak Sidelobe Level (PSLL) and 3dB and 18dB bandwidth
  117. are found and checked.
  118. A publication from Sandia National Laboratories was used as reference
  119. for the correctness values [1]_.
  120. References
  121. -----
  122. .. [1] Armin Doerry, "Catalog of Window Taper Functions for
  123. Sidelobe Control", 2017.
  124. 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
  125. """
  126. M_win = 1024
  127. N_fft = 131072
  128. # Set norm=False for correctness as the values obtained from the
  129. # scientific publication do not normalize the values. Normalizing
  130. # changes the sidelobe level from the desired value.
  131. w = windows.taylor(M_win, nbar=4, sll=35, norm=False, sym=False)
  132. f = fft(w, N_fft)
  133. spec = 20 * np.log10(np.abs(f / np.amax(f)))
  134. first_zero = np.argmax(np.diff(spec) > 0)
  135. PSLL = np.amax(spec[first_zero:-first_zero])
  136. BW_3dB = 2*np.argmax(spec <= -3.0102999566398121) / N_fft * M_win
  137. BW_18dB = 2*np.argmax(spec <= -18.061799739838872) / N_fft * M_win
  138. assert_allclose(PSLL, -35.1672, atol=1)
  139. assert_allclose(BW_3dB, 1.1822, atol=0.1)
  140. assert_allclose(BW_18dB, 2.6112, atol=0.1)
  141. class TestBohman:
  142. def test_basic(self):
  143. assert_allclose(windows.bohman(6),
  144. [0, 0.1791238937062839, 0.8343114522576858,
  145. 0.8343114522576858, 0.1791238937062838, 0])
  146. assert_allclose(windows.bohman(7, sym=True),
  147. [0, 0.1089977810442293, 0.6089977810442293, 1.0,
  148. 0.6089977810442295, 0.1089977810442293, 0])
  149. assert_allclose(windows.bohman(6, False),
  150. [0, 0.1089977810442293, 0.6089977810442293, 1.0,
  151. 0.6089977810442295, 0.1089977810442293])
  152. class TestBoxcar:
  153. def test_basic(self):
  154. assert_allclose(windows.boxcar(6), [1, 1, 1, 1, 1, 1])
  155. assert_allclose(windows.boxcar(7), [1, 1, 1, 1, 1, 1, 1])
  156. assert_allclose(windows.boxcar(6, False), [1, 1, 1, 1, 1, 1])
  157. cheb_odd_true = array([0.200938, 0.107729, 0.134941, 0.165348,
  158. 0.198891, 0.235450, 0.274846, 0.316836,
  159. 0.361119, 0.407338, 0.455079, 0.503883,
  160. 0.553248, 0.602637, 0.651489, 0.699227,
  161. 0.745266, 0.789028, 0.829947, 0.867485,
  162. 0.901138, 0.930448, 0.955010, 0.974482,
  163. 0.988591, 0.997138, 1.000000, 0.997138,
  164. 0.988591, 0.974482, 0.955010, 0.930448,
  165. 0.901138, 0.867485, 0.829947, 0.789028,
  166. 0.745266, 0.699227, 0.651489, 0.602637,
  167. 0.553248, 0.503883, 0.455079, 0.407338,
  168. 0.361119, 0.316836, 0.274846, 0.235450,
  169. 0.198891, 0.165348, 0.134941, 0.107729,
  170. 0.200938])
  171. cheb_even_true = array([0.203894, 0.107279, 0.133904,
  172. 0.163608, 0.196338, 0.231986,
  173. 0.270385, 0.311313, 0.354493,
  174. 0.399594, 0.446233, 0.493983,
  175. 0.542378, 0.590916, 0.639071,
  176. 0.686302, 0.732055, 0.775783,
  177. 0.816944, 0.855021, 0.889525,
  178. 0.920006, 0.946060, 0.967339,
  179. 0.983557, 0.994494, 1.000000,
  180. 1.000000, 0.994494, 0.983557,
  181. 0.967339, 0.946060, 0.920006,
  182. 0.889525, 0.855021, 0.816944,
  183. 0.775783, 0.732055, 0.686302,
  184. 0.639071, 0.590916, 0.542378,
  185. 0.493983, 0.446233, 0.399594,
  186. 0.354493, 0.311313, 0.270385,
  187. 0.231986, 0.196338, 0.163608,
  188. 0.133904, 0.107279, 0.203894])
  189. class TestChebWin:
  190. def test_basic(self):
  191. with suppress_warnings() as sup:
  192. sup.filter(UserWarning, "This window is not suitable")
  193. assert_allclose(windows.chebwin(6, 100),
  194. [0.1046401879356917, 0.5075781475823447, 1.0, 1.0,
  195. 0.5075781475823447, 0.1046401879356917])
  196. assert_allclose(windows.chebwin(7, 100),
  197. [0.05650405062850233, 0.316608530648474,
  198. 0.7601208123539079, 1.0, 0.7601208123539079,
  199. 0.316608530648474, 0.05650405062850233])
  200. assert_allclose(windows.chebwin(6, 10),
  201. [1.0, 0.6071201674458373, 0.6808391469897297,
  202. 0.6808391469897297, 0.6071201674458373, 1.0])
  203. assert_allclose(windows.chebwin(7, 10),
  204. [1.0, 0.5190521247588651, 0.5864059018130382,
  205. 0.6101519801307441, 0.5864059018130382,
  206. 0.5190521247588651, 1.0])
  207. assert_allclose(windows.chebwin(6, 10, False),
  208. [1.0, 0.5190521247588651, 0.5864059018130382,
  209. 0.6101519801307441, 0.5864059018130382,
  210. 0.5190521247588651])
  211. def test_cheb_odd_high_attenuation(self):
  212. with suppress_warnings() as sup:
  213. sup.filter(UserWarning, "This window is not suitable")
  214. cheb_odd = windows.chebwin(53, at=-40)
  215. assert_array_almost_equal(cheb_odd, cheb_odd_true, decimal=4)
  216. def test_cheb_even_high_attenuation(self):
  217. with suppress_warnings() as sup:
  218. sup.filter(UserWarning, "This window is not suitable")
  219. cheb_even = windows.chebwin(54, at=40)
  220. assert_array_almost_equal(cheb_even, cheb_even_true, decimal=4)
  221. def test_cheb_odd_low_attenuation(self):
  222. cheb_odd_low_at_true = array([1.000000, 0.519052, 0.586405,
  223. 0.610151, 0.586405, 0.519052,
  224. 1.000000])
  225. with suppress_warnings() as sup:
  226. sup.filter(UserWarning, "This window is not suitable")
  227. cheb_odd = windows.chebwin(7, at=10)
  228. assert_array_almost_equal(cheb_odd, cheb_odd_low_at_true, decimal=4)
  229. def test_cheb_even_low_attenuation(self):
  230. cheb_even_low_at_true = array([1.000000, 0.451924, 0.51027,
  231. 0.541338, 0.541338, 0.51027,
  232. 0.451924, 1.000000])
  233. with suppress_warnings() as sup:
  234. sup.filter(UserWarning, "This window is not suitable")
  235. cheb_even = windows.chebwin(8, at=-10)
  236. assert_array_almost_equal(cheb_even, cheb_even_low_at_true, decimal=4)
  237. exponential_data = {
  238. (4, None, 0.2, False):
  239. array([4.53999297624848542e-05,
  240. 6.73794699908546700e-03, 1.00000000000000000e+00,
  241. 6.73794699908546700e-03]),
  242. (4, None, 0.2, True): array([0.00055308437014783, 0.0820849986238988,
  243. 0.0820849986238988, 0.00055308437014783]),
  244. (4, None, 1.0, False): array([0.1353352832366127, 0.36787944117144233, 1.,
  245. 0.36787944117144233]),
  246. (4, None, 1.0, True): array([0.22313016014842982, 0.60653065971263342,
  247. 0.60653065971263342, 0.22313016014842982]),
  248. (4, 2, 0.2, False):
  249. array([4.53999297624848542e-05, 6.73794699908546700e-03,
  250. 1.00000000000000000e+00, 6.73794699908546700e-03]),
  251. (4, 2, 0.2, True): None,
  252. (4, 2, 1.0, False): array([0.1353352832366127, 0.36787944117144233, 1.,
  253. 0.36787944117144233]),
  254. (4, 2, 1.0, True): None,
  255. (5, None, 0.2, True):
  256. array([4.53999297624848542e-05,
  257. 6.73794699908546700e-03, 1.00000000000000000e+00,
  258. 6.73794699908546700e-03, 4.53999297624848542e-05]),
  259. (5, None, 1.0, True): array([0.1353352832366127, 0.36787944117144233, 1.,
  260. 0.36787944117144233, 0.1353352832366127]),
  261. (5, 2, 0.2, True): None,
  262. (5, 2, 1.0, True): None
  263. }
  264. def test_exponential():
  265. for k, v in exponential_data.items():
  266. if v is None:
  267. assert_raises(ValueError, windows.exponential, *k)
  268. else:
  269. win = windows.exponential(*k)
  270. assert_allclose(win, v, rtol=1e-14)
  271. class TestFlatTop:
  272. def test_basic(self):
  273. assert_allclose(windows.flattop(6, sym=False),
  274. [-0.000421051, -0.051263156, 0.19821053, 1.0,
  275. 0.19821053, -0.051263156])
  276. assert_allclose(windows.flattop(7, sym=False),
  277. [-0.000421051, -0.03684078115492348,
  278. 0.01070371671615342, 0.7808739149387698,
  279. 0.7808739149387698, 0.01070371671615342,
  280. -0.03684078115492348])
  281. assert_allclose(windows.flattop(6),
  282. [-0.000421051, -0.0677142520762119, 0.6068721525762117,
  283. 0.6068721525762117, -0.0677142520762119,
  284. -0.000421051])
  285. assert_allclose(windows.flattop(7, True),
  286. [-0.000421051, -0.051263156, 0.19821053, 1.0,
  287. 0.19821053, -0.051263156, -0.000421051])
  288. class TestGaussian:
  289. def test_basic(self):
  290. assert_allclose(windows.gaussian(6, 1.0),
  291. [0.04393693362340742, 0.3246524673583497,
  292. 0.8824969025845955, 0.8824969025845955,
  293. 0.3246524673583497, 0.04393693362340742])
  294. assert_allclose(windows.gaussian(7, 1.2),
  295. [0.04393693362340742, 0.2493522087772962,
  296. 0.7066482778577162, 1.0, 0.7066482778577162,
  297. 0.2493522087772962, 0.04393693362340742])
  298. assert_allclose(windows.gaussian(7, 3),
  299. [0.6065306597126334, 0.8007374029168081,
  300. 0.9459594689067654, 1.0, 0.9459594689067654,
  301. 0.8007374029168081, 0.6065306597126334])
  302. assert_allclose(windows.gaussian(6, 3, False),
  303. [0.6065306597126334, 0.8007374029168081,
  304. 0.9459594689067654, 1.0, 0.9459594689067654,
  305. 0.8007374029168081])
  306. class TestGeneralCosine:
  307. def test_basic(self):
  308. assert_allclose(windows.general_cosine(5, [0.5, 0.3, 0.2]),
  309. [0.4, 0.3, 1, 0.3, 0.4])
  310. assert_allclose(windows.general_cosine(4, [0.5, 0.3, 0.2], sym=False),
  311. [0.4, 0.3, 1, 0.3])
  312. class TestGeneralHamming:
  313. def test_basic(self):
  314. assert_allclose(windows.general_hamming(5, 0.7),
  315. [0.4, 0.7, 1.0, 0.7, 0.4])
  316. assert_allclose(windows.general_hamming(5, 0.75, sym=False),
  317. [0.5, 0.6727457514, 0.9522542486,
  318. 0.9522542486, 0.6727457514])
  319. assert_allclose(windows.general_hamming(6, 0.75, sym=True),
  320. [0.5, 0.6727457514, 0.9522542486,
  321. 0.9522542486, 0.6727457514, 0.5])
  322. class TestHamming:
  323. def test_basic(self):
  324. assert_allclose(windows.hamming(6, False),
  325. [0.08, 0.31, 0.77, 1.0, 0.77, 0.31])
  326. assert_allclose(windows.hamming(7, sym=False),
  327. [0.08, 0.2531946911449826, 0.6423596296199047,
  328. 0.9544456792351128, 0.9544456792351128,
  329. 0.6423596296199047, 0.2531946911449826])
  330. assert_allclose(windows.hamming(6),
  331. [0.08, 0.3978521825875242, 0.9121478174124757,
  332. 0.9121478174124757, 0.3978521825875242, 0.08])
  333. assert_allclose(windows.hamming(7, sym=True),
  334. [0.08, 0.31, 0.77, 1.0, 0.77, 0.31, 0.08])
  335. class TestHann:
  336. def test_basic(self):
  337. assert_allclose(windows.hann(6, sym=False),
  338. [0, 0.25, 0.75, 1.0, 0.75, 0.25])
  339. assert_allclose(windows.hann(7, sym=False),
  340. [0, 0.1882550990706332, 0.6112604669781572,
  341. 0.9504844339512095, 0.9504844339512095,
  342. 0.6112604669781572, 0.1882550990706332])
  343. assert_allclose(windows.hann(6, True),
  344. [0, 0.3454915028125263, 0.9045084971874737,
  345. 0.9045084971874737, 0.3454915028125263, 0])
  346. assert_allclose(windows.hann(7),
  347. [0, 0.25, 0.75, 1.0, 0.75, 0.25, 0])
  348. class TestKaiser:
  349. def test_basic(self):
  350. assert_allclose(windows.kaiser(6, 0.5),
  351. [0.9403061933191572, 0.9782962393705389,
  352. 0.9975765035372042, 0.9975765035372042,
  353. 0.9782962393705389, 0.9403061933191572])
  354. assert_allclose(windows.kaiser(7, 0.5),
  355. [0.9403061933191572, 0.9732402256999829,
  356. 0.9932754654413773, 1.0, 0.9932754654413773,
  357. 0.9732402256999829, 0.9403061933191572])
  358. assert_allclose(windows.kaiser(6, 2.7),
  359. [0.2603047507678832, 0.6648106293528054,
  360. 0.9582099802511439, 0.9582099802511439,
  361. 0.6648106293528054, 0.2603047507678832])
  362. assert_allclose(windows.kaiser(7, 2.7),
  363. [0.2603047507678832, 0.5985765418119844,
  364. 0.8868495172060835, 1.0, 0.8868495172060835,
  365. 0.5985765418119844, 0.2603047507678832])
  366. assert_allclose(windows.kaiser(6, 2.7, False),
  367. [0.2603047507678832, 0.5985765418119844,
  368. 0.8868495172060835, 1.0, 0.8868495172060835,
  369. 0.5985765418119844])
  370. class TestKaiserBesselDerived:
  371. def test_basic(self):
  372. M = 100
  373. w = windows.kaiser_bessel_derived(M, beta=4.0)
  374. w2 = windows.get_window(('kaiser bessel derived', 4.0),
  375. M, fftbins=False)
  376. assert_allclose(w, w2)
  377. # Test for Princen-Bradley condition
  378. assert_allclose(w[:M // 2] ** 2 + w[-M // 2:] ** 2, 1.)
  379. # Test actual values from other implementations
  380. # M = 2: sqrt(2) / 2
  381. # M = 4: 0.518562710536, 0.855039598640
  382. # M = 6: 0.436168993154, 0.707106781187, 0.899864772847
  383. # Ref:https://github.com/scipy/scipy/pull/4747#issuecomment-172849418
  384. assert_allclose(windows.kaiser_bessel_derived(2, beta=np.pi / 2)[:1],
  385. np.sqrt(2) / 2)
  386. assert_allclose(windows.kaiser_bessel_derived(4, beta=np.pi / 2)[:2],
  387. [0.518562710536, 0.855039598640])
  388. assert_allclose(windows.kaiser_bessel_derived(6, beta=np.pi / 2)[:3],
  389. [0.436168993154, 0.707106781187, 0.899864772847])
  390. def test_exceptions(self):
  391. M = 100
  392. # Assert ValueError for odd window length
  393. msg = ("Kaiser-Bessel Derived windows are only defined for even "
  394. "number of points")
  395. with assert_raises(ValueError, match=msg):
  396. windows.kaiser_bessel_derived(M + 1, beta=4.)
  397. # Assert ValueError for non-symmetric setting
  398. msg = ("Kaiser-Bessel Derived windows are only defined for "
  399. "symmetric shapes")
  400. with assert_raises(ValueError, match=msg):
  401. windows.kaiser_bessel_derived(M + 1, beta=4., sym=False)
  402. class TestNuttall:
  403. def test_basic(self):
  404. assert_allclose(windows.nuttall(6, sym=False),
  405. [0.0003628, 0.0613345, 0.5292298, 1.0, 0.5292298,
  406. 0.0613345])
  407. assert_allclose(windows.nuttall(7, sym=False),
  408. [0.0003628, 0.03777576895352025, 0.3427276199688195,
  409. 0.8918518610776603, 0.8918518610776603,
  410. 0.3427276199688196, 0.0377757689535203])
  411. assert_allclose(windows.nuttall(6),
  412. [0.0003628, 0.1105152530498718, 0.7982580969501282,
  413. 0.7982580969501283, 0.1105152530498719, 0.0003628])
  414. assert_allclose(windows.nuttall(7, True),
  415. [0.0003628, 0.0613345, 0.5292298, 1.0, 0.5292298,
  416. 0.0613345, 0.0003628])
  417. class TestParzen:
  418. def test_basic(self):
  419. assert_allclose(windows.parzen(6),
  420. [0.009259259259259254, 0.25, 0.8611111111111112,
  421. 0.8611111111111112, 0.25, 0.009259259259259254])
  422. assert_allclose(windows.parzen(7, sym=True),
  423. [0.00583090379008747, 0.1574344023323616,
  424. 0.6501457725947521, 1.0, 0.6501457725947521,
  425. 0.1574344023323616, 0.00583090379008747])
  426. assert_allclose(windows.parzen(6, False),
  427. [0.00583090379008747, 0.1574344023323616,
  428. 0.6501457725947521, 1.0, 0.6501457725947521,
  429. 0.1574344023323616])
  430. class TestTriang:
  431. def test_basic(self):
  432. assert_allclose(windows.triang(6, True),
  433. [1/6, 1/2, 5/6, 5/6, 1/2, 1/6])
  434. assert_allclose(windows.triang(7),
  435. [1/4, 1/2, 3/4, 1, 3/4, 1/2, 1/4])
  436. assert_allclose(windows.triang(6, sym=False),
  437. [1/4, 1/2, 3/4, 1, 3/4, 1/2])
  438. tukey_data = {
  439. (4, 0.5, True): array([0.0, 1.0, 1.0, 0.0]),
  440. (4, 0.9, True): array([0.0, 0.84312081893436686,
  441. 0.84312081893436686, 0.0]),
  442. (4, 1.0, True): array([0.0, 0.75, 0.75, 0.0]),
  443. (4, 0.5, False): array([0.0, 1.0, 1.0, 1.0]),
  444. (4, 0.9, False): array([0.0, 0.58682408883346526,
  445. 1.0, 0.58682408883346526]),
  446. (4, 1.0, False): array([0.0, 0.5, 1.0, 0.5]),
  447. (5, 0.0, True): array([1.0, 1.0, 1.0, 1.0, 1.0]),
  448. (5, 0.8, True): array([0.0, 0.69134171618254492,
  449. 1.0, 0.69134171618254492, 0.0]),
  450. (5, 1.0, True): array([0.0, 0.5, 1.0, 0.5, 0.0]),
  451. (6, 0): [1, 1, 1, 1, 1, 1],
  452. (7, 0): [1, 1, 1, 1, 1, 1, 1],
  453. (6, .25): [0, 1, 1, 1, 1, 0],
  454. (7, .25): [0, 1, 1, 1, 1, 1, 0],
  455. (6,): [0, 0.9045084971874737, 1.0, 1.0, 0.9045084971874735, 0],
  456. (7,): [0, 0.75, 1.0, 1.0, 1.0, 0.75, 0],
  457. (6, .75): [0, 0.5522642316338269, 1.0, 1.0, 0.5522642316338267, 0],
  458. (7, .75): [0, 0.4131759111665348, 0.9698463103929542, 1.0,
  459. 0.9698463103929542, 0.4131759111665347, 0],
  460. (6, 1): [0, 0.3454915028125263, 0.9045084971874737, 0.9045084971874737,
  461. 0.3454915028125263, 0],
  462. (7, 1): [0, 0.25, 0.75, 1.0, 0.75, 0.25, 0],
  463. }
  464. class TestTukey:
  465. def test_basic(self):
  466. # Test against hardcoded data
  467. for k, v in tukey_data.items():
  468. if v is None:
  469. assert_raises(ValueError, windows.tukey, *k)
  470. else:
  471. win = windows.tukey(*k)
  472. assert_allclose(win, v, rtol=1e-14)
  473. def test_extremes(self):
  474. # Test extremes of alpha correspond to boxcar and hann
  475. tuk0 = windows.tukey(100, 0)
  476. box0 = windows.boxcar(100)
  477. assert_array_almost_equal(tuk0, box0)
  478. tuk1 = windows.tukey(100, 1)
  479. han1 = windows.hann(100)
  480. assert_array_almost_equal(tuk1, han1)
  481. dpss_data = {
  482. # All values from MATLAB:
  483. # * taper[1] of (3, 1.4, 3) sign-flipped
  484. # * taper[3] of (5, 1.5, 5) sign-flipped
  485. (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
  486. (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
  487. (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
  488. (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
  489. }
  490. class TestDPSS:
  491. def test_basic(self):
  492. # Test against hardcoded data
  493. for k, v in dpss_data.items():
  494. win, ratios = windows.dpss(*k, return_ratios=True)
  495. assert_allclose(win, v[0], atol=1e-7, err_msg=k)
  496. assert_allclose(ratios, v[1], rtol=1e-5, atol=1e-7, err_msg=k)
  497. def test_unity(self):
  498. # Test unity value handling (gh-2221)
  499. for M in range(1, 21):
  500. # corrected w/approximation (default)
  501. win = windows.dpss(M, M / 2.1)
  502. expected = M % 2 # one for odd, none for even
  503. assert_equal(np.isclose(win, 1.).sum(), expected,
  504. err_msg='%s' % (win,))
  505. # corrected w/subsample delay (slower)
  506. win_sub = windows.dpss(M, M / 2.1, norm='subsample')
  507. if M > 2:
  508. # @M=2 the subsample doesn't do anything
  509. assert_equal(np.isclose(win_sub, 1.).sum(), expected,
  510. err_msg='%s' % (win_sub,))
  511. assert_allclose(win, win_sub, rtol=0.03) # within 3%
  512. # not the same, l2-norm
  513. win_2 = windows.dpss(M, M / 2.1, norm=2)
  514. expected = 1 if M == 1 else 0
  515. assert_equal(np.isclose(win_2, 1.).sum(), expected,
  516. err_msg='%s' % (win_2,))
  517. def test_extremes(self):
  518. # Test extremes of alpha
  519. lam = windows.dpss(31, 6, 4, return_ratios=True)[1]
  520. assert_array_almost_equal(lam, 1.)
  521. lam = windows.dpss(31, 7, 4, return_ratios=True)[1]
  522. assert_array_almost_equal(lam, 1.)
  523. lam = windows.dpss(31, 8, 4, return_ratios=True)[1]
  524. assert_array_almost_equal(lam, 1.)
  525. def test_degenerate(self):
  526. # Test failures
  527. assert_raises(ValueError, windows.dpss, 4, 1.5, -1) # Bad Kmax
  528. assert_raises(ValueError, windows.dpss, 4, 1.5, -5)
  529. assert_raises(TypeError, windows.dpss, 4, 1.5, 1.1)
  530. assert_raises(ValueError, windows.dpss, 3, 1.5, 3) # NW must be < N/2.
  531. assert_raises(ValueError, windows.dpss, 3, -1, 3) # NW must be pos
  532. assert_raises(ValueError, windows.dpss, 3, 0, 3)
  533. assert_raises(ValueError, windows.dpss, -1, 1, 3) # negative M
  534. class TestLanczos:
  535. def test_basic(self):
  536. # Analytical results:
  537. # sinc(x) = sinc(-x)
  538. # sinc(pi) = 0, sinc(0) = 1
  539. # Hand computation on WolframAlpha:
  540. # sinc(2 pi / 3) = 0.413496672
  541. # sinc(pi / 3) = 0.826993343
  542. # sinc(3 pi / 5) = 0.504551152
  543. # sinc(pi / 5) = 0.935489284
  544. assert_allclose(windows.lanczos(6, sym=False),
  545. [0., 0.413496672,
  546. 0.826993343, 1., 0.826993343,
  547. 0.413496672],
  548. atol=1e-9)
  549. assert_allclose(windows.lanczos(6),
  550. [0., 0.504551152,
  551. 0.935489284, 0.935489284,
  552. 0.504551152, 0.],
  553. atol=1e-9)
  554. assert_allclose(windows.lanczos(7, sym=True),
  555. [0., 0.413496672,
  556. 0.826993343, 1., 0.826993343,
  557. 0.413496672, 0.],
  558. atol=1e-9)
  559. def test_array_size(self):
  560. for n in [0, 10, 11]:
  561. assert_equal(len(windows.lanczos(n, sym=False)), n)
  562. assert_equal(len(windows.lanczos(n, sym=True)), n)
  563. class TestGetWindow:
  564. def test_boxcar(self):
  565. w = windows.get_window('boxcar', 12)
  566. assert_array_equal(w, np.ones_like(w))
  567. # window is a tuple of len 1
  568. w = windows.get_window(('boxcar',), 16)
  569. assert_array_equal(w, np.ones_like(w))
  570. def test_cheb_odd(self):
  571. with suppress_warnings() as sup:
  572. sup.filter(UserWarning, "This window is not suitable")
  573. w = windows.get_window(('chebwin', -40), 53, fftbins=False)
  574. assert_array_almost_equal(w, cheb_odd_true, decimal=4)
  575. def test_cheb_even(self):
  576. with suppress_warnings() as sup:
  577. sup.filter(UserWarning, "This window is not suitable")
  578. w = windows.get_window(('chebwin', 40), 54, fftbins=False)
  579. assert_array_almost_equal(w, cheb_even_true, decimal=4)
  580. def test_dpss(self):
  581. win1 = windows.get_window(('dpss', 3), 64, fftbins=False)
  582. win2 = windows.dpss(64, 3)
  583. assert_array_almost_equal(win1, win2, decimal=4)
  584. def test_kaiser_float(self):
  585. win1 = windows.get_window(7.2, 64)
  586. win2 = windows.kaiser(64, 7.2, False)
  587. assert_allclose(win1, win2)
  588. def test_invalid_inputs(self):
  589. # Window is not a float, tuple, or string
  590. assert_raises(ValueError, windows.get_window, set('hann'), 8)
  591. # Unknown window type error
  592. assert_raises(ValueError, windows.get_window, 'broken', 4)
  593. def test_array_as_window(self):
  594. # github issue 3603
  595. osfactor = 128
  596. sig = np.arange(128)
  597. win = windows.get_window(('kaiser', 8.0), osfactor // 2)
  598. with assert_raises(ValueError, match='must have the same length'):
  599. resample(sig, len(sig) * osfactor, window=win)
  600. def test_general_cosine(self):
  601. assert_allclose(get_window(('general_cosine', [0.5, 0.3, 0.2]), 4),
  602. [0.4, 0.3, 1, 0.3])
  603. assert_allclose(get_window(('general_cosine', [0.5, 0.3, 0.2]), 4,
  604. fftbins=False),
  605. [0.4, 0.55, 0.55, 0.4])
  606. def test_general_hamming(self):
  607. assert_allclose(get_window(('general_hamming', 0.7), 5),
  608. [0.4, 0.6072949, 0.9427051, 0.9427051, 0.6072949])
  609. assert_allclose(get_window(('general_hamming', 0.7), 5, fftbins=False),
  610. [0.4, 0.7, 1.0, 0.7, 0.4])
  611. def test_lanczos(self):
  612. assert_allclose(get_window('lanczos', 6),
  613. [0., 0.413496672, 0.826993343, 1., 0.826993343,
  614. 0.413496672], atol=1e-9)
  615. assert_allclose(get_window('lanczos', 6, fftbins=False),
  616. [0., 0.504551152, 0.935489284, 0.935489284,
  617. 0.504551152, 0.], atol=1e-9)
  618. assert_allclose(get_window('lanczos', 6), get_window('sinc', 6))
  619. def test_windowfunc_basics():
  620. for window_name, params in window_funcs:
  621. window = getattr(windows, window_name)
  622. with suppress_warnings() as sup:
  623. sup.filter(UserWarning, "This window is not suitable")
  624. # Check symmetry for odd and even lengths
  625. w1 = window(8, *params, sym=True)
  626. w2 = window(7, *params, sym=False)
  627. assert_array_almost_equal(w1[:-1], w2)
  628. w1 = window(9, *params, sym=True)
  629. w2 = window(8, *params, sym=False)
  630. assert_array_almost_equal(w1[:-1], w2)
  631. # Check that functions run and output lengths are correct
  632. assert_equal(len(window(6, *params, sym=True)), 6)
  633. assert_equal(len(window(6, *params, sym=False)), 6)
  634. assert_equal(len(window(7, *params, sym=True)), 7)
  635. assert_equal(len(window(7, *params, sym=False)), 7)
  636. # Check invalid lengths
  637. assert_raises(ValueError, window, 5.5, *params)
  638. assert_raises(ValueError, window, -7, *params)
  639. # Check degenerate cases
  640. assert_array_equal(window(0, *params, sym=True), [])
  641. assert_array_equal(window(0, *params, sym=False), [])
  642. assert_array_equal(window(1, *params, sym=True), [1])
  643. assert_array_equal(window(1, *params, sym=False), [1])
  644. # Check dtype
  645. assert_(window(0, *params, sym=True).dtype == 'float')
  646. assert_(window(0, *params, sym=False).dtype == 'float')
  647. assert_(window(1, *params, sym=True).dtype == 'float')
  648. assert_(window(1, *params, sym=False).dtype == 'float')
  649. assert_(window(6, *params, sym=True).dtype == 'float')
  650. assert_(window(6, *params, sym=False).dtype == 'float')
  651. # Check normalization
  652. assert_array_less(window(10, *params, sym=True), 1.01)
  653. assert_array_less(window(10, *params, sym=False), 1.01)
  654. assert_array_less(window(9, *params, sym=True), 1.01)
  655. assert_array_less(window(9, *params, sym=False), 1.01)
  656. # Check that DFT-even spectrum is purely real for odd and even
  657. assert_allclose(fft(window(10, *params, sym=False)).imag,
  658. 0, atol=1e-14)
  659. assert_allclose(fft(window(11, *params, sym=False)).imag,
  660. 0, atol=1e-14)
  661. def test_needs_params():
  662. for winstr in ['kaiser', 'ksr', 'kaiser_bessel_derived', 'kbd',
  663. 'gaussian', 'gauss', 'gss',
  664. 'general gaussian', 'general_gaussian',
  665. 'general gauss', 'general_gauss', 'ggs',
  666. 'dss', 'dpss', 'general cosine', 'general_cosine',
  667. 'chebwin', 'cheb', 'general hamming', 'general_hamming',
  668. ]:
  669. assert_raises(ValueError, get_window, winstr, 7)
  670. def test_not_needs_params():
  671. for winstr in ['barthann',
  672. 'bartlett',
  673. 'blackman',
  674. 'blackmanharris',
  675. 'bohman',
  676. 'boxcar',
  677. 'cosine',
  678. 'flattop',
  679. 'hamming',
  680. 'nuttall',
  681. 'parzen',
  682. 'taylor',
  683. 'exponential',
  684. 'poisson',
  685. 'tukey',
  686. 'tuk',
  687. 'triangle',
  688. 'lanczos',
  689. 'sinc',
  690. ]:
  691. win = get_window(winstr, 7)
  692. assert_equal(len(win), 7)
  693. def test_deprecation():
  694. if dep_hann.__doc__ is not None: # can be None with `-OO` mode
  695. assert_('signal.hann is deprecated' in dep_hann.__doc__)
  696. assert_('deprecated' not in windows.hann.__doc__)
  697. def test_deprecated_pickleable():
  698. dep_hann2 = pickle.loads(pickle.dumps(dep_hann))
  699. assert_(dep_hann2 is dep_hann)
  700. def test_symmetric():
  701. for win in [windows.lanczos]:
  702. # Even sampling points
  703. w = win(4096)
  704. error = np.max(np.abs(w-np.flip(w)))
  705. assert_equal(error, 0.0)
  706. # Odd sampling points
  707. w = win(4097)
  708. error = np.max(np.abs(w-np.flip(w)))
  709. assert_equal(error, 0.0)