Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/scipy/signal/windows/windows.py : 15%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""The suite of window functions."""
3import operator
4import warnings
6import numpy as np
7from scipy import linalg, special, fft as sp_fft
9__all__ = ['boxcar', 'triang', 'parzen', 'bohman', 'blackman', 'nuttall',
10 'blackmanharris', 'flattop', 'bartlett', 'hanning', 'barthann',
11 'hamming', 'kaiser', 'gaussian', 'general_cosine','general_gaussian',
12 'general_hamming', 'chebwin', 'slepian', 'cosine', 'hann',
13 'exponential', 'tukey', 'dpss', 'get_window']
16def _len_guards(M):
17 """Handle small or incorrect window lengths"""
18 if int(M) != M or M < 0:
19 raise ValueError('Window length M must be a non-negative integer')
20 return M <= 1
23def _extend(M, sym):
24 """Extend window by 1 sample if needed for DFT-even symmetry"""
25 if not sym:
26 return M + 1, True
27 else:
28 return M, False
31def _truncate(w, needed):
32 """Truncate window by 1 sample if needed for DFT-even symmetry"""
33 if needed:
34 return w[:-1]
35 else:
36 return w
39def general_cosine(M, a, sym=True):
40 r"""
41 Generic weighted sum of cosine terms window
43 Parameters
44 ----------
45 M : int
46 Number of points in the output window
47 a : array_like
48 Sequence of weighting coefficients. This uses the convention of being
49 centered on the origin, so these will typically all be positive
50 numbers, not alternating sign.
51 sym : bool, optional
52 When True (default), generates a symmetric window, for use in filter
53 design.
54 When False, generates a periodic window, for use in spectral analysis.
56 References
57 ----------
58 .. [1] A. Nuttall, "Some windows with very good sidelobe behavior," IEEE
59 Transactions on Acoustics, Speech, and Signal Processing, vol. 29,
60 no. 1, pp. 84-91, Feb 1981. :doi:`10.1109/TASSP.1981.1163506`.
61 .. [2] Heinzel G. et al., "Spectrum and spectral density estimation by the
62 Discrete Fourier transform (DFT), including a comprehensive list of
63 window functions and some new flat-top windows", February 15, 2002
64 https://holometer.fnal.gov/GH_FFT.pdf
66 Examples
67 --------
68 Heinzel describes a flat-top window named "HFT90D" with formula: [2]_
70 .. math:: w_j = 1 - 1.942604 \cos(z) + 1.340318 \cos(2z)
71 - 0.440811 \cos(3z) + 0.043097 \cos(4z)
73 where
75 .. math:: z = \frac{2 \pi j}{N}, j = 0...N - 1
77 Since this uses the convention of starting at the origin, to reproduce the
78 window, we need to convert every other coefficient to a positive number:
80 >>> HFT90D = [1, 1.942604, 1.340318, 0.440811, 0.043097]
82 The paper states that the highest sidelobe is at -90.2 dB. Reproduce
83 Figure 42 by plotting the window and its frequency response, and confirm
84 the sidelobe level in red:
86 >>> from scipy.signal.windows import general_cosine
87 >>> from scipy.fft import fft, fftshift
88 >>> import matplotlib.pyplot as plt
90 >>> window = general_cosine(1000, HFT90D, sym=False)
91 >>> plt.plot(window)
92 >>> plt.title("HFT90D window")
93 >>> plt.ylabel("Amplitude")
94 >>> plt.xlabel("Sample")
96 >>> plt.figure()
97 >>> A = fft(window, 10000) / (len(window)/2.0)
98 >>> freq = np.linspace(-0.5, 0.5, len(A))
99 >>> response = np.abs(fftshift(A / abs(A).max()))
100 >>> response = 20 * np.log10(np.maximum(response, 1e-10))
101 >>> plt.plot(freq, response)
102 >>> plt.axis([-50/1000, 50/1000, -140, 0])
103 >>> plt.title("Frequency response of the HFT90D window")
104 >>> plt.ylabel("Normalized magnitude [dB]")
105 >>> plt.xlabel("Normalized frequency [cycles per sample]")
106 >>> plt.axhline(-90.2, color='red')
107 >>> plt.show()
108 """
109 if _len_guards(M):
110 return np.ones(M)
111 M, needs_trunc = _extend(M, sym)
113 fac = np.linspace(-np.pi, np.pi, M)
114 w = np.zeros(M)
115 for k in range(len(a)):
116 w += a[k] * np.cos(k * fac)
118 return _truncate(w, needs_trunc)
121def boxcar(M, sym=True):
122 """Return a boxcar or rectangular window.
124 Also known as a rectangular window or Dirichlet window, this is equivalent
125 to no window at all.
127 Parameters
128 ----------
129 M : int
130 Number of points in the output window. If zero or less, an empty
131 array is returned.
132 sym : bool, optional
133 Whether the window is symmetric. (Has no effect for boxcar.)
135 Returns
136 -------
137 w : ndarray
138 The window, with the maximum value normalized to 1.
140 Examples
141 --------
142 Plot the window and its frequency response:
144 >>> from scipy import signal
145 >>> from scipy.fft import fft, fftshift
146 >>> import matplotlib.pyplot as plt
148 >>> window = signal.boxcar(51)
149 >>> plt.plot(window)
150 >>> plt.title("Boxcar window")
151 >>> plt.ylabel("Amplitude")
152 >>> plt.xlabel("Sample")
154 >>> plt.figure()
155 >>> A = fft(window, 2048) / (len(window)/2.0)
156 >>> freq = np.linspace(-0.5, 0.5, len(A))
157 >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max())))
158 >>> plt.plot(freq, response)
159 >>> plt.axis([-0.5, 0.5, -120, 0])
160 >>> plt.title("Frequency response of the boxcar window")
161 >>> plt.ylabel("Normalized magnitude [dB]")
162 >>> plt.xlabel("Normalized frequency [cycles per sample]")
164 """
165 if _len_guards(M):
166 return np.ones(M)
167 M, needs_trunc = _extend(M, sym)
169 w = np.ones(M, float)
171 return _truncate(w, needs_trunc)
174def triang(M, sym=True):
175 """Return a triangular window.
177 Parameters
178 ----------
179 M : int
180 Number of points in the output window. If zero or less, an empty
181 array is returned.
182 sym : bool, optional
183 When True (default), generates a symmetric window, for use in filter
184 design.
185 When False, generates a periodic window, for use in spectral analysis.
187 Returns
188 -------
189 w : ndarray
190 The window, with the maximum value normalized to 1 (though the value 1
191 does not appear if `M` is even and `sym` is True).
193 See Also
194 --------
195 bartlett : A triangular window that touches zero
197 Examples
198 --------
199 Plot the window and its frequency response:
201 >>> from scipy import signal
202 >>> from scipy.fft import fft, fftshift
203 >>> import matplotlib.pyplot as plt
205 >>> window = signal.triang(51)
206 >>> plt.plot(window)
207 >>> plt.title("Triangular window")
208 >>> plt.ylabel("Amplitude")
209 >>> plt.xlabel("Sample")
211 >>> plt.figure()
212 >>> A = fft(window, 2048) / (len(window)/2.0)
213 >>> freq = np.linspace(-0.5, 0.5, len(A))
214 >>> response = np.abs(fftshift(A / abs(A).max()))
215 >>> response = 20 * np.log10(np.maximum(response, 1e-10))
216 >>> plt.plot(freq, response)
217 >>> plt.axis([-0.5, 0.5, -120, 0])
218 >>> plt.title("Frequency response of the triangular window")
219 >>> plt.ylabel("Normalized magnitude [dB]")
220 >>> plt.xlabel("Normalized frequency [cycles per sample]")
222 """
223 if _len_guards(M):
224 return np.ones(M)
225 M, needs_trunc = _extend(M, sym)
227 n = np.arange(1, (M + 1) // 2 + 1)
228 if M % 2 == 0:
229 w = (2 * n - 1.0) / M
230 w = np.r_[w, w[::-1]]
231 else:
232 w = 2 * n / (M + 1.0)
233 w = np.r_[w, w[-2::-1]]
235 return _truncate(w, needs_trunc)
238def parzen(M, sym=True):
239 """Return a Parzen window.
241 Parameters
242 ----------
243 M : int
244 Number of points in the output window. If zero or less, an empty
245 array is returned.
246 sym : bool, optional
247 When True (default), generates a symmetric window, for use in filter
248 design.
249 When False, generates a periodic window, for use in spectral analysis.
251 Returns
252 -------
253 w : ndarray
254 The window, with the maximum value normalized to 1 (though the value 1
255 does not appear if `M` is even and `sym` is True).
257 References
258 ----------
259 .. [1] E. Parzen, "Mathematical Considerations in the Estimation of
260 Spectra", Technometrics, Vol. 3, No. 2 (May, 1961), pp. 167-190
262 Examples
263 --------
264 Plot the window and its frequency response:
266 >>> from scipy import signal
267 >>> from scipy.fft import fft, fftshift
268 >>> import matplotlib.pyplot as plt
270 >>> window = signal.parzen(51)
271 >>> plt.plot(window)
272 >>> plt.title("Parzen window")
273 >>> plt.ylabel("Amplitude")
274 >>> plt.xlabel("Sample")
276 >>> plt.figure()
277 >>> A = fft(window, 2048) / (len(window)/2.0)
278 >>> freq = np.linspace(-0.5, 0.5, len(A))
279 >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max())))
280 >>> plt.plot(freq, response)
281 >>> plt.axis([-0.5, 0.5, -120, 0])
282 >>> plt.title("Frequency response of the Parzen window")
283 >>> plt.ylabel("Normalized magnitude [dB]")
284 >>> plt.xlabel("Normalized frequency [cycles per sample]")
286 """
287 if _len_guards(M):
288 return np.ones(M)
289 M, needs_trunc = _extend(M, sym)
291 n = np.arange(-(M - 1) / 2.0, (M - 1) / 2.0 + 0.5, 1.0)
292 na = np.extract(n < -(M - 1) / 4.0, n)
293 nb = np.extract(abs(n) <= (M - 1) / 4.0, n)
294 wa = 2 * (1 - np.abs(na) / (M / 2.0)) ** 3.0
295 wb = (1 - 6 * (np.abs(nb) / (M / 2.0)) ** 2.0 +
296 6 * (np.abs(nb) / (M / 2.0)) ** 3.0)
297 w = np.r_[wa, wb, wa[::-1]]
299 return _truncate(w, needs_trunc)
302def bohman(M, sym=True):
303 """Return a Bohman window.
305 Parameters
306 ----------
307 M : int
308 Number of points in the output window. If zero or less, an empty
309 array is returned.
310 sym : bool, optional
311 When True (default), generates a symmetric window, for use in filter
312 design.
313 When False, generates a periodic window, for use in spectral analysis.
315 Returns
316 -------
317 w : ndarray
318 The window, with the maximum value normalized to 1 (though the value 1
319 does not appear if `M` is even and `sym` is True).
321 Examples
322 --------
323 Plot the window and its frequency response:
325 >>> from scipy import signal
326 >>> from scipy.fft import fft, fftshift
327 >>> import matplotlib.pyplot as plt
329 >>> window = signal.bohman(51)
330 >>> plt.plot(window)
331 >>> plt.title("Bohman window")
332 >>> plt.ylabel("Amplitude")
333 >>> plt.xlabel("Sample")
335 >>> plt.figure()
336 >>> A = fft(window, 2048) / (len(window)/2.0)
337 >>> freq = np.linspace(-0.5, 0.5, len(A))
338 >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max())))
339 >>> plt.plot(freq, response)
340 >>> plt.axis([-0.5, 0.5, -120, 0])
341 >>> plt.title("Frequency response of the Bohman window")
342 >>> plt.ylabel("Normalized magnitude [dB]")
343 >>> plt.xlabel("Normalized frequency [cycles per sample]")
345 """
346 if _len_guards(M):
347 return np.ones(M)
348 M, needs_trunc = _extend(M, sym)
350 fac = np.abs(np.linspace(-1, 1, M)[1:-1])
351 w = (1 - fac) * np.cos(np.pi * fac) + 1.0 / np.pi * np.sin(np.pi * fac)
352 w = np.r_[0, w, 0]
354 return _truncate(w, needs_trunc)
357def blackman(M, sym=True):
358 r"""
359 Return a Blackman window.
361 The Blackman window is a taper formed by using the first three terms of
362 a summation of cosines. It was designed to have close to the minimal
363 leakage possible. It is close to optimal, only slightly worse than a
364 Kaiser window.
366 Parameters
367 ----------
368 M : int
369 Number of points in the output window. If zero or less, an empty
370 array is returned.
371 sym : bool, optional
372 When True (default), generates a symmetric window, for use in filter
373 design.
374 When False, generates a periodic window, for use in spectral analysis.
376 Returns
377 -------
378 w : ndarray
379 The window, with the maximum value normalized to 1 (though the value 1
380 does not appear if `M` is even and `sym` is True).
382 Notes
383 -----
384 The Blackman window is defined as
386 .. math:: w(n) = 0.42 - 0.5 \cos(2\pi n/M) + 0.08 \cos(4\pi n/M)
388 The "exact Blackman" window was designed to null out the third and fourth
389 sidelobes, but has discontinuities at the boundaries, resulting in a
390 6 dB/oct fall-off. This window is an approximation of the "exact" window,
391 which does not null the sidelobes as well, but is smooth at the edges,
392 improving the fall-off rate to 18 dB/oct. [3]_
394 Most references to the Blackman window come from the signal processing
395 literature, where it is used as one of many windowing functions for
396 smoothing values. It is also known as an apodization (which means
397 "removing the foot", i.e. smoothing discontinuities at the beginning
398 and end of the sampled signal) or tapering function. It is known as a
399 "near optimal" tapering function, almost as good (by some measures)
400 as the Kaiser window.
402 References
403 ----------
404 .. [1] Blackman, R.B. and Tukey, J.W., (1958) The measurement of power
405 spectra, Dover Publications, New York.
406 .. [2] Oppenheim, A.V., and R.W. Schafer. Discrete-Time Signal Processing.
407 Upper Saddle River, NJ: Prentice-Hall, 1999, pp. 468-471.
408 .. [3] Harris, Fredric J. (Jan 1978). "On the use of Windows for Harmonic
409 Analysis with the Discrete Fourier Transform". Proceedings of the
410 IEEE 66 (1): 51-83. :doi:`10.1109/PROC.1978.10837`.
412 Examples
413 --------
414 Plot the window and its frequency response:
416 >>> from scipy import signal
417 >>> from scipy.fft import fft, fftshift
418 >>> import matplotlib.pyplot as plt
420 >>> window = signal.blackman(51)
421 >>> plt.plot(window)
422 >>> plt.title("Blackman window")
423 >>> plt.ylabel("Amplitude")
424 >>> plt.xlabel("Sample")
426 >>> plt.figure()
427 >>> A = fft(window, 2048) / (len(window)/2.0)
428 >>> freq = np.linspace(-0.5, 0.5, len(A))
429 >>> response = np.abs(fftshift(A / abs(A).max()))
430 >>> response = 20 * np.log10(np.maximum(response, 1e-10))
431 >>> plt.plot(freq, response)
432 >>> plt.axis([-0.5, 0.5, -120, 0])
433 >>> plt.title("Frequency response of the Blackman window")
434 >>> plt.ylabel("Normalized magnitude [dB]")
435 >>> plt.xlabel("Normalized frequency [cycles per sample]")
437 """
438 # Docstring adapted from NumPy's blackman function
439 return general_cosine(M, [0.42, 0.50, 0.08], sym)
442def nuttall(M, sym=True):
443 """Return a minimum 4-term Blackman-Harris window according to Nuttall.
445 This variation is called "Nuttall4c" by Heinzel. [2]_
447 Parameters
448 ----------
449 M : int
450 Number of points in the output window. If zero or less, an empty
451 array is returned.
452 sym : bool, optional
453 When True (default), generates a symmetric window, for use in filter
454 design.
455 When False, generates a periodic window, for use in spectral analysis.
457 Returns
458 -------
459 w : ndarray
460 The window, with the maximum value normalized to 1 (though the value 1
461 does not appear if `M` is even and `sym` is True).
463 References
464 ----------
465 .. [1] A. Nuttall, "Some windows with very good sidelobe behavior," IEEE
466 Transactions on Acoustics, Speech, and Signal Processing, vol. 29,
467 no. 1, pp. 84-91, Feb 1981. :doi:`10.1109/TASSP.1981.1163506`.
468 .. [2] Heinzel G. et al., "Spectrum and spectral density estimation by the
469 Discrete Fourier transform (DFT), including a comprehensive list of
470 window functions and some new flat-top windows", February 15, 2002
471 https://holometer.fnal.gov/GH_FFT.pdf
473 Examples
474 --------
475 Plot the window and its frequency response:
477 >>> from scipy import signal
478 >>> from scipy.fft import fft, fftshift
479 >>> import matplotlib.pyplot as plt
481 >>> window = signal.nuttall(51)
482 >>> plt.plot(window)
483 >>> plt.title("Nuttall window")
484 >>> plt.ylabel("Amplitude")
485 >>> plt.xlabel("Sample")
487 >>> plt.figure()
488 >>> A = fft(window, 2048) / (len(window)/2.0)
489 >>> freq = np.linspace(-0.5, 0.5, len(A))
490 >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max())))
491 >>> plt.plot(freq, response)
492 >>> plt.axis([-0.5, 0.5, -120, 0])
493 >>> plt.title("Frequency response of the Nuttall window")
494 >>> plt.ylabel("Normalized magnitude [dB]")
495 >>> plt.xlabel("Normalized frequency [cycles per sample]")
497 """
498 return general_cosine(M, [0.3635819, 0.4891775, 0.1365995, 0.0106411], sym)
501def blackmanharris(M, sym=True):
502 """Return a minimum 4-term Blackman-Harris window.
504 Parameters
505 ----------
506 M : int
507 Number of points in the output window. If zero or less, an empty
508 array is returned.
509 sym : bool, optional
510 When True (default), generates a symmetric window, for use in filter
511 design.
512 When False, generates a periodic window, for use in spectral analysis.
514 Returns
515 -------
516 w : ndarray
517 The window, with the maximum value normalized to 1 (though the value 1
518 does not appear if `M` is even and `sym` is True).
520 Examples
521 --------
522 Plot the window and its frequency response:
524 >>> from scipy import signal
525 >>> from scipy.fft import fft, fftshift
526 >>> import matplotlib.pyplot as plt
528 >>> window = signal.blackmanharris(51)
529 >>> plt.plot(window)
530 >>> plt.title("Blackman-Harris window")
531 >>> plt.ylabel("Amplitude")
532 >>> plt.xlabel("Sample")
534 >>> plt.figure()
535 >>> A = fft(window, 2048) / (len(window)/2.0)
536 >>> freq = np.linspace(-0.5, 0.5, len(A))
537 >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max())))
538 >>> plt.plot(freq, response)
539 >>> plt.axis([-0.5, 0.5, -120, 0])
540 >>> plt.title("Frequency response of the Blackman-Harris window")
541 >>> plt.ylabel("Normalized magnitude [dB]")
542 >>> plt.xlabel("Normalized frequency [cycles per sample]")
544 """
545 return general_cosine(M, [0.35875, 0.48829, 0.14128, 0.01168], sym)
548def flattop(M, sym=True):
549 """Return a flat top window.
551 Parameters
552 ----------
553 M : int
554 Number of points in the output window. If zero or less, an empty
555 array is returned.
556 sym : bool, optional
557 When True (default), generates a symmetric window, for use in filter
558 design.
559 When False, generates a periodic window, for use in spectral analysis.
561 Returns
562 -------
563 w : ndarray
564 The window, with the maximum value normalized to 1 (though the value 1
565 does not appear if `M` is even and `sym` is True).
567 Notes
568 -----
569 Flat top windows are used for taking accurate measurements of signal
570 amplitude in the frequency domain, with minimal scalloping error from the
571 center of a frequency bin to its edges, compared to others. This is a
572 5th-order cosine window, with the 5 terms optimized to make the main lobe
573 maximally flat. [1]_
575 References
576 ----------
577 .. [1] D'Antona, Gabriele, and A. Ferrero, "Digital Signal Processing for
578 Measurement Systems", Springer Media, 2006, p. 70
579 :doi:`10.1007/0-387-28666-7`.
581 Examples
582 --------
583 Plot the window and its frequency response:
585 >>> from scipy import signal
586 >>> from scipy.fft import fft, fftshift
587 >>> import matplotlib.pyplot as plt
589 >>> window = signal.flattop(51)
590 >>> plt.plot(window)
591 >>> plt.title("Flat top window")
592 >>> plt.ylabel("Amplitude")
593 >>> plt.xlabel("Sample")
595 >>> plt.figure()
596 >>> A = fft(window, 2048) / (len(window)/2.0)
597 >>> freq = np.linspace(-0.5, 0.5, len(A))
598 >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max())))
599 >>> plt.plot(freq, response)
600 >>> plt.axis([-0.5, 0.5, -120, 0])
601 >>> plt.title("Frequency response of the flat top window")
602 >>> plt.ylabel("Normalized magnitude [dB]")
603 >>> plt.xlabel("Normalized frequency [cycles per sample]")
605 """
606 a = [0.21557895, 0.41663158, 0.277263158, 0.083578947, 0.006947368]
607 return general_cosine(M, a, sym)
610def bartlett(M, sym=True):
611 r"""
612 Return a Bartlett window.
614 The Bartlett window is very similar to a triangular window, except
615 that the end points are at zero. It is often used in signal
616 processing for tapering a signal, without generating too much
617 ripple in the frequency domain.
619 Parameters
620 ----------
621 M : int
622 Number of points in the output window. If zero or less, an empty
623 array is returned.
624 sym : bool, optional
625 When True (default), generates a symmetric window, for use in filter
626 design.
627 When False, generates a periodic window, for use in spectral analysis.
629 Returns
630 -------
631 w : ndarray
632 The triangular window, with the first and last samples equal to zero
633 and the maximum value normalized to 1 (though the value 1 does not
634 appear if `M` is even and `sym` is True).
636 See Also
637 --------
638 triang : A triangular window that does not touch zero at the ends
640 Notes
641 -----
642 The Bartlett window is defined as
644 .. math:: w(n) = \frac{2}{M-1} \left(
645 \frac{M-1}{2} - \left|n - \frac{M-1}{2}\right|
646 \right)
648 Most references to the Bartlett window come from the signal
649 processing literature, where it is used as one of many windowing
650 functions for smoothing values. Note that convolution with this
651 window produces linear interpolation. It is also known as an
652 apodization (which means"removing the foot", i.e. smoothing
653 discontinuities at the beginning and end of the sampled signal) or
654 tapering function. The Fourier transform of the Bartlett is the product
655 of two sinc functions.
656 Note the excellent discussion in Kanasewich. [2]_
658 References
659 ----------
660 .. [1] M.S. Bartlett, "Periodogram Analysis and Continuous Spectra",
661 Biometrika 37, 1-16, 1950.
662 .. [2] E.R. Kanasewich, "Time Sequence Analysis in Geophysics",
663 The University of Alberta Press, 1975, pp. 109-110.
664 .. [3] A.V. Oppenheim and R.W. Schafer, "Discrete-Time Signal
665 Processing", Prentice-Hall, 1999, pp. 468-471.
666 .. [4] Wikipedia, "Window function",
667 https://en.wikipedia.org/wiki/Window_function
668 .. [5] W.H. Press, B.P. Flannery, S.A. Teukolsky, and W.T. Vetterling,
669 "Numerical Recipes", Cambridge University Press, 1986, page 429.
671 Examples
672 --------
673 Plot the window and its frequency response:
675 >>> from scipy import signal
676 >>> from scipy.fft import fft, fftshift
677 >>> import matplotlib.pyplot as plt
679 >>> window = signal.bartlett(51)
680 >>> plt.plot(window)
681 >>> plt.title("Bartlett window")
682 >>> plt.ylabel("Amplitude")
683 >>> plt.xlabel("Sample")
685 >>> plt.figure()
686 >>> A = fft(window, 2048) / (len(window)/2.0)
687 >>> freq = np.linspace(-0.5, 0.5, len(A))
688 >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max())))
689 >>> plt.plot(freq, response)
690 >>> plt.axis([-0.5, 0.5, -120, 0])
691 >>> plt.title("Frequency response of the Bartlett window")
692 >>> plt.ylabel("Normalized magnitude [dB]")
693 >>> plt.xlabel("Normalized frequency [cycles per sample]")
695 """
696 # Docstring adapted from NumPy's bartlett function
697 if _len_guards(M):
698 return np.ones(M)
699 M, needs_trunc = _extend(M, sym)
701 n = np.arange(0, M)
702 w = np.where(np.less_equal(n, (M - 1) / 2.0),
703 2.0 * n / (M - 1), 2.0 - 2.0 * n / (M - 1))
705 return _truncate(w, needs_trunc)
708def hann(M, sym=True):
709 r"""
710 Return a Hann window.
712 The Hann window is a taper formed by using a raised cosine or sine-squared
713 with ends that touch zero.
715 Parameters
716 ----------
717 M : int
718 Number of points in the output window. If zero or less, an empty
719 array is returned.
720 sym : bool, optional
721 When True (default), generates a symmetric window, for use in filter
722 design.
723 When False, generates a periodic window, for use in spectral analysis.
725 Returns
726 -------
727 w : ndarray
728 The window, with the maximum value normalized to 1 (though the value 1
729 does not appear if `M` is even and `sym` is True).
731 Notes
732 -----
733 The Hann window is defined as
735 .. math:: w(n) = 0.5 - 0.5 \cos\left(\frac{2\pi{n}}{M-1}\right)
736 \qquad 0 \leq n \leq M-1
738 The window was named for Julius von Hann, an Austrian meteorologist. It is
739 also known as the Cosine Bell. It is sometimes erroneously referred to as
740 the "Hanning" window, from the use of "hann" as a verb in the original
741 paper and confusion with the very similar Hamming window.
743 Most references to the Hann window come from the signal processing
744 literature, where it is used as one of many windowing functions for
745 smoothing values. It is also known as an apodization (which means
746 "removing the foot", i.e. smoothing discontinuities at the beginning
747 and end of the sampled signal) or tapering function.
749 References
750 ----------
751 .. [1] Blackman, R.B. and Tukey, J.W., (1958) The measurement of power
752 spectra, Dover Publications, New York.
753 .. [2] E.R. Kanasewich, "Time Sequence Analysis in Geophysics",
754 The University of Alberta Press, 1975, pp. 106-108.
755 .. [3] Wikipedia, "Window function",
756 https://en.wikipedia.org/wiki/Window_function
757 .. [4] W.H. Press, B.P. Flannery, S.A. Teukolsky, and W.T. Vetterling,
758 "Numerical Recipes", Cambridge University Press, 1986, page 425.
760 Examples
761 --------
762 Plot the window and its frequency response:
764 >>> from scipy import signal
765 >>> from scipy.fft import fft, fftshift
766 >>> import matplotlib.pyplot as plt
768 >>> window = signal.hann(51)
769 >>> plt.plot(window)
770 >>> plt.title("Hann window")
771 >>> plt.ylabel("Amplitude")
772 >>> plt.xlabel("Sample")
774 >>> plt.figure()
775 >>> A = fft(window, 2048) / (len(window)/2.0)
776 >>> freq = np.linspace(-0.5, 0.5, len(A))
777 >>> response = np.abs(fftshift(A / abs(A).max()))
778 >>> response = 20 * np.log10(np.maximum(response, 1e-10))
779 >>> plt.plot(freq, response)
780 >>> plt.axis([-0.5, 0.5, -120, 0])
781 >>> plt.title("Frequency response of the Hann window")
782 >>> plt.ylabel("Normalized magnitude [dB]")
783 >>> plt.xlabel("Normalized frequency [cycles per sample]")
785 """
786 # Docstring adapted from NumPy's hanning function
787 return general_hamming(M, 0.5, sym)
790@np.deprecate(new_name='scipy.signal.windows.hann')
791def hanning(*args, **kwargs):
792 return hann(*args, **kwargs)
795def tukey(M, alpha=0.5, sym=True):
796 r"""Return a Tukey window, also known as a tapered cosine window.
798 Parameters
799 ----------
800 M : int
801 Number of points in the output window. If zero or less, an empty
802 array is returned.
803 alpha : float, optional
804 Shape parameter of the Tukey window, representing the fraction of the
805 window inside the cosine tapered region.
806 If zero, the Tukey window is equivalent to a rectangular window.
807 If one, the Tukey window is equivalent to a Hann window.
808 sym : bool, optional
809 When True (default), generates a symmetric window, for use in filter
810 design.
811 When False, generates a periodic window, for use in spectral analysis.
813 Returns
814 -------
815 w : ndarray
816 The window, with the maximum value normalized to 1 (though the value 1
817 does not appear if `M` is even and `sym` is True).
819 References
820 ----------
821 .. [1] Harris, Fredric J. (Jan 1978). "On the use of Windows for Harmonic
822 Analysis with the Discrete Fourier Transform". Proceedings of the
823 IEEE 66 (1): 51-83. :doi:`10.1109/PROC.1978.10837`
824 .. [2] Wikipedia, "Window function",
825 https://en.wikipedia.org/wiki/Window_function#Tukey_window
827 Examples
828 --------
829 Plot the window and its frequency response:
831 >>> from scipy import signal
832 >>> from scipy.fft import fft, fftshift
833 >>> import matplotlib.pyplot as plt
835 >>> window = signal.tukey(51)
836 >>> plt.plot(window)
837 >>> plt.title("Tukey window")
838 >>> plt.ylabel("Amplitude")
839 >>> plt.xlabel("Sample")
840 >>> plt.ylim([0, 1.1])
842 >>> plt.figure()
843 >>> A = fft(window, 2048) / (len(window)/2.0)
844 >>> freq = np.linspace(-0.5, 0.5, len(A))
845 >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max())))
846 >>> plt.plot(freq, response)
847 >>> plt.axis([-0.5, 0.5, -120, 0])
848 >>> plt.title("Frequency response of the Tukey window")
849 >>> plt.ylabel("Normalized magnitude [dB]")
850 >>> plt.xlabel("Normalized frequency [cycles per sample]")
852 """
853 if _len_guards(M):
854 return np.ones(M)
856 if alpha <= 0:
857 return np.ones(M, 'd')
858 elif alpha >= 1.0:
859 return hann(M, sym=sym)
861 M, needs_trunc = _extend(M, sym)
863 n = np.arange(0, M)
864 width = int(np.floor(alpha*(M-1)/2.0))
865 n1 = n[0:width+1]
866 n2 = n[width+1:M-width-1]
867 n3 = n[M-width-1:]
869 w1 = 0.5 * (1 + np.cos(np.pi * (-1 + 2.0*n1/alpha/(M-1))))
870 w2 = np.ones(n2.shape)
871 w3 = 0.5 * (1 + np.cos(np.pi * (-2.0/alpha + 1 + 2.0*n3/alpha/(M-1))))
873 w = np.concatenate((w1, w2, w3))
875 return _truncate(w, needs_trunc)
878def barthann(M, sym=True):
879 """Return a modified Bartlett-Hann window.
881 Parameters
882 ----------
883 M : int
884 Number of points in the output window. If zero or less, an empty
885 array is returned.
886 sym : bool, optional
887 When True (default), generates a symmetric window, for use in filter
888 design.
889 When False, generates a periodic window, for use in spectral analysis.
891 Returns
892 -------
893 w : ndarray
894 The window, with the maximum value normalized to 1 (though the value 1
895 does not appear if `M` is even and `sym` is True).
897 Examples
898 --------
899 Plot the window and its frequency response:
901 >>> from scipy import signal
902 >>> from scipy.fft import fft, fftshift
903 >>> import matplotlib.pyplot as plt
905 >>> window = signal.barthann(51)
906 >>> plt.plot(window)
907 >>> plt.title("Bartlett-Hann window")
908 >>> plt.ylabel("Amplitude")
909 >>> plt.xlabel("Sample")
911 >>> plt.figure()
912 >>> A = fft(window, 2048) / (len(window)/2.0)
913 >>> freq = np.linspace(-0.5, 0.5, len(A))
914 >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max())))
915 >>> plt.plot(freq, response)
916 >>> plt.axis([-0.5, 0.5, -120, 0])
917 >>> plt.title("Frequency response of the Bartlett-Hann window")
918 >>> plt.ylabel("Normalized magnitude [dB]")
919 >>> plt.xlabel("Normalized frequency [cycles per sample]")
921 """
922 if _len_guards(M):
923 return np.ones(M)
924 M, needs_trunc = _extend(M, sym)
926 n = np.arange(0, M)
927 fac = np.abs(n / (M - 1.0) - 0.5)
928 w = 0.62 - 0.48 * fac + 0.38 * np.cos(2 * np.pi * fac)
930 return _truncate(w, needs_trunc)
933def general_hamming(M, alpha, sym=True):
934 r"""Return a generalized Hamming window.
936 The generalized Hamming window is constructed by multiplying a rectangular
937 window by one period of a cosine function [1]_.
939 Parameters
940 ----------
941 M : int
942 Number of points in the output window. If zero or less, an empty
943 array is returned.
944 alpha : float
945 The window coefficient, :math:`\alpha`
946 sym : bool, optional
947 When True (default), generates a symmetric window, for use in filter
948 design.
949 When False, generates a periodic window, for use in spectral analysis.
951 Returns
952 -------
953 w : ndarray
954 The window, with the maximum value normalized to 1 (though the value 1
955 does not appear if `M` is even and `sym` is True).
957 Notes
958 -----
959 The generalized Hamming window is defined as
961 .. math:: w(n) = \alpha - \left(1 - \alpha\right) \cos\left(\frac{2\pi{n}}{M-1}\right)
962 \qquad 0 \leq n \leq M-1
964 Both the common Hamming window and Hann window are special cases of the
965 generalized Hamming window with :math:`\alpha` = 0.54 and :math:`\alpha` =
966 0.5, respectively [2]_.
968 See Also
969 --------
970 hamming, hann
972 Examples
973 --------
974 The Sentinel-1A/B Instrument Processing Facility uses generalized Hamming
975 windows in the processing of spaceborne Synthetic Aperture Radar (SAR)
976 data [3]_. The facility uses various values for the :math:`\alpha`
977 parameter based on operating mode of the SAR instrument. Some common
978 :math:`\alpha` values include 0.75, 0.7 and 0.52 [4]_. As an example, we
979 plot these different windows.
981 >>> from scipy.signal.windows import general_hamming
982 >>> from scipy.fft import fft, fftshift
983 >>> import matplotlib.pyplot as plt
985 >>> fig1, spatial_plot = plt.subplots()
986 >>> spatial_plot.set_title("Generalized Hamming Windows")
987 >>> spatial_plot.set_ylabel("Amplitude")
988 >>> spatial_plot.set_xlabel("Sample")
990 >>> fig2, freq_plot = plt.subplots()
991 >>> freq_plot.set_title("Frequency Responses")
992 >>> freq_plot.set_ylabel("Normalized magnitude [dB]")
993 >>> freq_plot.set_xlabel("Normalized frequency [cycles per sample]")
995 >>> for alpha in [0.75, 0.7, 0.52]:
996 ... window = general_hamming(41, alpha)
997 ... spatial_plot.plot(window, label="{:.2f}".format(alpha))
998 ... A = fft(window, 2048) / (len(window)/2.0)
999 ... freq = np.linspace(-0.5, 0.5, len(A))
1000 ... response = 20 * np.log10(np.abs(fftshift(A / abs(A).max())))
1001 ... freq_plot.plot(freq, response, label="{:.2f}".format(alpha))
1002 >>> freq_plot.legend(loc="upper right")
1003 >>> spatial_plot.legend(loc="upper right")
1005 References
1006 ----------
1007 .. [1] DSPRelated, "Generalized Hamming Window Family",
1008 https://www.dsprelated.com/freebooks/sasp/Generalized_Hamming_Window_Family.html
1009 .. [2] Wikipedia, "Window function",
1010 https://en.wikipedia.org/wiki/Window_function
1011 .. [3] Riccardo Piantanida ESA, "Sentinel-1 Level 1 Detailed Algorithm
1012 Definition",
1013 https://sentinel.esa.int/documents/247904/1877131/Sentinel-1-Level-1-Detailed-Algorithm-Definition
1014 .. [4] Matthieu Bourbigot ESA, "Sentinel-1 Product Definition",
1015 https://sentinel.esa.int/documents/247904/1877131/Sentinel-1-Product-Definition
1016 """
1017 return general_cosine(M, [alpha, 1. - alpha], sym)
1020def hamming(M, sym=True):
1021 r"""Return a Hamming window.
1023 The Hamming window is a taper formed by using a raised cosine with
1024 non-zero endpoints, optimized to minimize the nearest side lobe.
1026 Parameters
1027 ----------
1028 M : int
1029 Number of points in the output window. If zero or less, an empty
1030 array is returned.
1031 sym : bool, optional
1032 When True (default), generates a symmetric window, for use in filter
1033 design.
1034 When False, generates a periodic window, for use in spectral analysis.
1036 Returns
1037 -------
1038 w : ndarray
1039 The window, with the maximum value normalized to 1 (though the value 1
1040 does not appear if `M` is even and `sym` is True).
1042 Notes
1043 -----
1044 The Hamming window is defined as
1046 .. math:: w(n) = 0.54 - 0.46 \cos\left(\frac{2\pi{n}}{M-1}\right)
1047 \qquad 0 \leq n \leq M-1
1049 The Hamming was named for R. W. Hamming, an associate of J. W. Tukey and
1050 is described in Blackman and Tukey. It was recommended for smoothing the
1051 truncated autocovariance function in the time domain.
1052 Most references to the Hamming window come from the signal processing
1053 literature, where it is used as one of many windowing functions for
1054 smoothing values. It is also known as an apodization (which means
1055 "removing the foot", i.e. smoothing discontinuities at the beginning
1056 and end of the sampled signal) or tapering function.
1058 References
1059 ----------
1060 .. [1] Blackman, R.B. and Tukey, J.W., (1958) The measurement of power
1061 spectra, Dover Publications, New York.
1062 .. [2] E.R. Kanasewich, "Time Sequence Analysis in Geophysics", The
1063 University of Alberta Press, 1975, pp. 109-110.
1064 .. [3] Wikipedia, "Window function",
1065 https://en.wikipedia.org/wiki/Window_function
1066 .. [4] W.H. Press, B.P. Flannery, S.A. Teukolsky, and W.T. Vetterling,
1067 "Numerical Recipes", Cambridge University Press, 1986, page 425.
1069 Examples
1070 --------
1071 Plot the window and its frequency response:
1073 >>> from scipy import signal
1074 >>> from scipy.fft import fft, fftshift
1075 >>> import matplotlib.pyplot as plt
1077 >>> window = signal.hamming(51)
1078 >>> plt.plot(window)
1079 >>> plt.title("Hamming window")
1080 >>> plt.ylabel("Amplitude")
1081 >>> plt.xlabel("Sample")
1083 >>> plt.figure()
1084 >>> A = fft(window, 2048) / (len(window)/2.0)
1085 >>> freq = np.linspace(-0.5, 0.5, len(A))
1086 >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max())))
1087 >>> plt.plot(freq, response)
1088 >>> plt.axis([-0.5, 0.5, -120, 0])
1089 >>> plt.title("Frequency response of the Hamming window")
1090 >>> plt.ylabel("Normalized magnitude [dB]")
1091 >>> plt.xlabel("Normalized frequency [cycles per sample]")
1093 """
1094 # Docstring adapted from NumPy's hamming function
1095 return general_hamming(M, 0.54, sym)
1098def kaiser(M, beta, sym=True):
1099 r"""Return a Kaiser window.
1101 The Kaiser window is a taper formed by using a Bessel function.
1103 Parameters
1104 ----------
1105 M : int
1106 Number of points in the output window. If zero or less, an empty
1107 array is returned.
1108 beta : float
1109 Shape parameter, determines trade-off between main-lobe width and
1110 side lobe level. As beta gets large, the window narrows.
1111 sym : bool, optional
1112 When True (default), generates a symmetric window, for use in filter
1113 design.
1114 When False, generates a periodic window, for use in spectral analysis.
1116 Returns
1117 -------
1118 w : ndarray
1119 The window, with the maximum value normalized to 1 (though the value 1
1120 does not appear if `M` is even and `sym` is True).
1122 Notes
1123 -----
1124 The Kaiser window is defined as
1126 .. math:: w(n) = I_0\left( \beta \sqrt{1-\frac{4n^2}{(M-1)^2}}
1127 \right)/I_0(\beta)
1129 with
1131 .. math:: \quad -\frac{M-1}{2} \leq n \leq \frac{M-1}{2},
1133 where :math:`I_0` is the modified zeroth-order Bessel function.
1135 The Kaiser was named for Jim Kaiser, who discovered a simple approximation
1136 to the DPSS window based on Bessel functions.
1137 The Kaiser window is a very good approximation to the Digital Prolate
1138 Spheroidal Sequence, or Slepian window, which is the transform which
1139 maximizes the energy in the main lobe of the window relative to total
1140 energy.
1142 The Kaiser can approximate other windows by varying the beta parameter.
1143 (Some literature uses alpha = beta/pi.) [4]_
1145 ==== =======================
1146 beta Window shape
1147 ==== =======================
1148 0 Rectangular
1149 5 Similar to a Hamming
1150 6 Similar to a Hann
1151 8.6 Similar to a Blackman
1152 ==== =======================
1154 A beta value of 14 is probably a good starting point. Note that as beta
1155 gets large, the window narrows, and so the number of samples needs to be
1156 large enough to sample the increasingly narrow spike, otherwise NaNs will
1157 be returned.
1159 Most references to the Kaiser window come from the signal processing
1160 literature, where it is used as one of many windowing functions for
1161 smoothing values. It is also known as an apodization (which means
1162 "removing the foot", i.e. smoothing discontinuities at the beginning
1163 and end of the sampled signal) or tapering function.
1165 References
1166 ----------
1167 .. [1] J. F. Kaiser, "Digital Filters" - Ch 7 in "Systems analysis by
1168 digital computer", Editors: F.F. Kuo and J.F. Kaiser, p 218-285.
1169 John Wiley and Sons, New York, (1966).
1170 .. [2] E.R. Kanasewich, "Time Sequence Analysis in Geophysics", The
1171 University of Alberta Press, 1975, pp. 177-178.
1172 .. [3] Wikipedia, "Window function",
1173 https://en.wikipedia.org/wiki/Window_function
1174 .. [4] F. J. Harris, "On the use of windows for harmonic analysis with the
1175 discrete Fourier transform," Proceedings of the IEEE, vol. 66,
1176 no. 1, pp. 51-83, Jan. 1978. :doi:`10.1109/PROC.1978.10837`.
1178 Examples
1179 --------
1180 Plot the window and its frequency response:
1182 >>> from scipy import signal
1183 >>> from scipy.fft import fft, fftshift
1184 >>> import matplotlib.pyplot as plt
1186 >>> window = signal.kaiser(51, beta=14)
1187 >>> plt.plot(window)
1188 >>> plt.title(r"Kaiser window ($\beta$=14)")
1189 >>> plt.ylabel("Amplitude")
1190 >>> plt.xlabel("Sample")
1192 >>> plt.figure()
1193 >>> A = fft(window, 2048) / (len(window)/2.0)
1194 >>> freq = np.linspace(-0.5, 0.5, len(A))
1195 >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max())))
1196 >>> plt.plot(freq, response)
1197 >>> plt.axis([-0.5, 0.5, -120, 0])
1198 >>> plt.title(r"Frequency response of the Kaiser window ($\beta$=14)")
1199 >>> plt.ylabel("Normalized magnitude [dB]")
1200 >>> plt.xlabel("Normalized frequency [cycles per sample]")
1202 """
1203 # Docstring adapted from NumPy's kaiser function
1204 if _len_guards(M):
1205 return np.ones(M)
1206 M, needs_trunc = _extend(M, sym)
1208 n = np.arange(0, M)
1209 alpha = (M - 1) / 2.0
1210 w = (special.i0(beta * np.sqrt(1 - ((n - alpha) / alpha) ** 2.0)) /
1211 special.i0(beta))
1213 return _truncate(w, needs_trunc)
1216def gaussian(M, std, sym=True):
1217 r"""Return a Gaussian window.
1219 Parameters
1220 ----------
1221 M : int
1222 Number of points in the output window. If zero or less, an empty
1223 array is returned.
1224 std : float
1225 The standard deviation, sigma.
1226 sym : bool, optional
1227 When True (default), generates a symmetric window, for use in filter
1228 design.
1229 When False, generates a periodic window, for use in spectral analysis.
1231 Returns
1232 -------
1233 w : ndarray
1234 The window, with the maximum value normalized to 1 (though the value 1
1235 does not appear if `M` is even and `sym` is True).
1237 Notes
1238 -----
1239 The Gaussian window is defined as
1241 .. math:: w(n) = e^{ -\frac{1}{2}\left(\frac{n}{\sigma}\right)^2 }
1243 Examples
1244 --------
1245 Plot the window and its frequency response:
1247 >>> from scipy import signal
1248 >>> from scipy.fft import fft, fftshift
1249 >>> import matplotlib.pyplot as plt
1251 >>> window = signal.gaussian(51, std=7)
1252 >>> plt.plot(window)
1253 >>> plt.title(r"Gaussian window ($\sigma$=7)")
1254 >>> plt.ylabel("Amplitude")
1255 >>> plt.xlabel("Sample")
1257 >>> plt.figure()
1258 >>> A = fft(window, 2048) / (len(window)/2.0)
1259 >>> freq = np.linspace(-0.5, 0.5, len(A))
1260 >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max())))
1261 >>> plt.plot(freq, response)
1262 >>> plt.axis([-0.5, 0.5, -120, 0])
1263 >>> plt.title(r"Frequency response of the Gaussian window ($\sigma$=7)")
1264 >>> plt.ylabel("Normalized magnitude [dB]")
1265 >>> plt.xlabel("Normalized frequency [cycles per sample]")
1267 """
1268 if _len_guards(M):
1269 return np.ones(M)
1270 M, needs_trunc = _extend(M, sym)
1272 n = np.arange(0, M) - (M - 1.0) / 2.0
1273 sig2 = 2 * std * std
1274 w = np.exp(-n ** 2 / sig2)
1276 return _truncate(w, needs_trunc)
1279def general_gaussian(M, p, sig, sym=True):
1280 r"""Return a window with a generalized Gaussian shape.
1282 Parameters
1283 ----------
1284 M : int
1285 Number of points in the output window. If zero or less, an empty
1286 array is returned.
1287 p : float
1288 Shape parameter. p = 1 is identical to `gaussian`, p = 0.5 is
1289 the same shape as the Laplace distribution.
1290 sig : float
1291 The standard deviation, sigma.
1292 sym : bool, optional
1293 When True (default), generates a symmetric window, for use in filter
1294 design.
1295 When False, generates a periodic window, for use in spectral analysis.
1297 Returns
1298 -------
1299 w : ndarray
1300 The window, with the maximum value normalized to 1 (though the value 1
1301 does not appear if `M` is even and `sym` is True).
1303 Notes
1304 -----
1305 The generalized Gaussian window is defined as
1307 .. math:: w(n) = e^{ -\frac{1}{2}\left|\frac{n}{\sigma}\right|^{2p} }
1309 the half-power point is at
1311 .. math:: (2 \log(2))^{1/(2 p)} \sigma
1313 Examples
1314 --------
1315 Plot the window and its frequency response:
1317 >>> from scipy import signal
1318 >>> from scipy.fft import fft, fftshift
1319 >>> import matplotlib.pyplot as plt
1321 >>> window = signal.general_gaussian(51, p=1.5, sig=7)
1322 >>> plt.plot(window)
1323 >>> plt.title(r"Generalized Gaussian window (p=1.5, $\sigma$=7)")
1324 >>> plt.ylabel("Amplitude")
1325 >>> plt.xlabel("Sample")
1327 >>> plt.figure()
1328 >>> A = fft(window, 2048) / (len(window)/2.0)
1329 >>> freq = np.linspace(-0.5, 0.5, len(A))
1330 >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max())))
1331 >>> plt.plot(freq, response)
1332 >>> plt.axis([-0.5, 0.5, -120, 0])
1333 >>> plt.title(r"Freq. resp. of the gen. Gaussian "
1334 ... r"window (p=1.5, $\sigma$=7)")
1335 >>> plt.ylabel("Normalized magnitude [dB]")
1336 >>> plt.xlabel("Normalized frequency [cycles per sample]")
1338 """
1339 if _len_guards(M):
1340 return np.ones(M)
1341 M, needs_trunc = _extend(M, sym)
1343 n = np.arange(0, M) - (M - 1.0) / 2.0
1344 w = np.exp(-0.5 * np.abs(n / sig) ** (2 * p))
1346 return _truncate(w, needs_trunc)
1349# `chebwin` contributed by Kumar Appaiah.
1350def chebwin(M, at, sym=True):
1351 r"""Return a Dolph-Chebyshev window.
1353 Parameters
1354 ----------
1355 M : int
1356 Number of points in the output window. If zero or less, an empty
1357 array is returned.
1358 at : float
1359 Attenuation (in dB).
1360 sym : bool, optional
1361 When True (default), generates a symmetric window, for use in filter
1362 design.
1363 When False, generates a periodic window, for use in spectral analysis.
1365 Returns
1366 -------
1367 w : ndarray
1368 The window, with the maximum value always normalized to 1
1370 Notes
1371 -----
1372 This window optimizes for the narrowest main lobe width for a given order
1373 `M` and sidelobe equiripple attenuation `at`, using Chebyshev
1374 polynomials. It was originally developed by Dolph to optimize the
1375 directionality of radio antenna arrays.
1377 Unlike most windows, the Dolph-Chebyshev is defined in terms of its
1378 frequency response:
1380 .. math:: W(k) = \frac
1381 {\cos\{M \cos^{-1}[\beta \cos(\frac{\pi k}{M})]\}}
1382 {\cosh[M \cosh^{-1}(\beta)]}
1384 where
1386 .. math:: \beta = \cosh \left [\frac{1}{M}
1387 \cosh^{-1}(10^\frac{A}{20}) \right ]
1389 and 0 <= abs(k) <= M-1. A is the attenuation in decibels (`at`).
1391 The time domain window is then generated using the IFFT, so
1392 power-of-two `M` are the fastest to generate, and prime number `M` are
1393 the slowest.
1395 The equiripple condition in the frequency domain creates impulses in the
1396 time domain, which appear at the ends of the window.
1398 References
1399 ----------
1400 .. [1] C. Dolph, "A current distribution for broadside arrays which
1401 optimizes the relationship between beam width and side-lobe level",
1402 Proceedings of the IEEE, Vol. 34, Issue 6
1403 .. [2] Peter Lynch, "The Dolph-Chebyshev Window: A Simple Optimal Filter",
1404 American Meteorological Society (April 1997)
1405 http://mathsci.ucd.ie/~plynch/Publications/Dolph.pdf
1406 .. [3] F. J. Harris, "On the use of windows for harmonic analysis with the
1407 discrete Fourier transforms", Proceedings of the IEEE, Vol. 66,
1408 No. 1, January 1978
1410 Examples
1411 --------
1412 Plot the window and its frequency response:
1414 >>> from scipy import signal
1415 >>> from scipy.fft import fft, fftshift
1416 >>> import matplotlib.pyplot as plt
1418 >>> window = signal.chebwin(51, at=100)
1419 >>> plt.plot(window)
1420 >>> plt.title("Dolph-Chebyshev window (100 dB)")
1421 >>> plt.ylabel("Amplitude")
1422 >>> plt.xlabel("Sample")
1424 >>> plt.figure()
1425 >>> A = fft(window, 2048) / (len(window)/2.0)
1426 >>> freq = np.linspace(-0.5, 0.5, len(A))
1427 >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max())))
1428 >>> plt.plot(freq, response)
1429 >>> plt.axis([-0.5, 0.5, -120, 0])
1430 >>> plt.title("Frequency response of the Dolph-Chebyshev window (100 dB)")
1431 >>> plt.ylabel("Normalized magnitude [dB]")
1432 >>> plt.xlabel("Normalized frequency [cycles per sample]")
1434 """
1435 if np.abs(at) < 45:
1436 warnings.warn("This window is not suitable for spectral analysis "
1437 "for attenuation values lower than about 45dB because "
1438 "the equivalent noise bandwidth of a Chebyshev window "
1439 "does not grow monotonically with increasing sidelobe "
1440 "attenuation when the attenuation is smaller than "
1441 "about 45 dB.")
1442 if _len_guards(M):
1443 return np.ones(M)
1444 M, needs_trunc = _extend(M, sym)
1446 # compute the parameter beta
1447 order = M - 1.0
1448 beta = np.cosh(1.0 / order * np.arccosh(10 ** (np.abs(at) / 20.)))
1449 k = np.r_[0:M] * 1.0
1450 x = beta * np.cos(np.pi * k / M)
1451 # Find the window's DFT coefficients
1452 # Use analytic definition of Chebyshev polynomial instead of expansion
1453 # from scipy.special. Using the expansion in scipy.special leads to errors.
1454 p = np.zeros(x.shape)
1455 p[x > 1] = np.cosh(order * np.arccosh(x[x > 1]))
1456 p[x < -1] = (2 * (M % 2) - 1) * np.cosh(order * np.arccosh(-x[x < -1]))
1457 p[np.abs(x) <= 1] = np.cos(order * np.arccos(x[np.abs(x) <= 1]))
1459 # Appropriate IDFT and filling up
1460 # depending on even/odd M
1461 if M % 2:
1462 w = np.real(sp_fft.fft(p))
1463 n = (M + 1) // 2
1464 w = w[:n]
1465 w = np.concatenate((w[n - 1:0:-1], w))
1466 else:
1467 p = p * np.exp(1.j * np.pi / M * np.r_[0:M])
1468 w = np.real(sp_fft.fft(p))
1469 n = M // 2 + 1
1470 w = np.concatenate((w[n - 1:0:-1], w[1:n]))
1471 w = w / max(w)
1473 return _truncate(w, needs_trunc)
1476def slepian(M, width, sym=True):
1477 """Return a digital Slepian (DPSS) window.
1479 Used to maximize the energy concentration in the main lobe. Also called
1480 the digital prolate spheroidal sequence (DPSS).
1482 .. note:: Deprecated in SciPy 1.1.
1483 `slepian` will be removed in a future version of SciPy, it is
1484 replaced by `dpss`, which uses the standard definition of a
1485 digital Slepian window.
1487 Parameters
1488 ----------
1489 M : int
1490 Number of points in the output window. If zero or less, an empty
1491 array is returned.
1492 width : float
1493 Bandwidth
1494 sym : bool, optional
1495 When True (default), generates a symmetric window, for use in filter
1496 design.
1497 When False, generates a periodic window, for use in spectral analysis.
1499 Returns
1500 -------
1501 w : ndarray
1502 The window, with the maximum value always normalized to 1
1504 See Also
1505 --------
1506 dpss
1508 References
1509 ----------
1510 .. [1] D. Slepian & H. O. Pollak: "Prolate spheroidal wave functions,
1511 Fourier analysis and uncertainty-I," Bell Syst. Tech. J., vol.40,
1512 pp.43-63, 1961. https://archive.org/details/bstj40-1-43
1513 .. [2] H. J. Landau & H. O. Pollak: "Prolate spheroidal wave functions,
1514 Fourier analysis and uncertainty-II," Bell Syst. Tech. J. , vol.40,
1515 pp.65-83, 1961. https://archive.org/details/bstj40-1-65
1517 Examples
1518 --------
1519 Plot the window and its frequency response:
1521 >>> from scipy import signal
1522 >>> from scipy.fft import fft, fftshift
1523 >>> import matplotlib.pyplot as plt
1525 >>> window = signal.slepian(51, width=0.3)
1526 >>> plt.plot(window)
1527 >>> plt.title("Slepian (DPSS) window (BW=0.3)")
1528 >>> plt.ylabel("Amplitude")
1529 >>> plt.xlabel("Sample")
1531 >>> plt.figure()
1532 >>> A = fft(window, 2048) / (len(window)/2.0)
1533 >>> freq = np.linspace(-0.5, 0.5, len(A))
1534 >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max())))
1535 >>> plt.plot(freq, response)
1536 >>> plt.axis([-0.5, 0.5, -120, 0])
1537 >>> plt.title("Frequency response of the Slepian window (BW=0.3)")
1538 >>> plt.ylabel("Normalized magnitude [dB]")
1539 >>> plt.xlabel("Normalized frequency [cycles per sample]")
1541 """
1542 warnings.warn('slepian is deprecated and will be removed in a future '
1543 'version, use dpss instead', DeprecationWarning)
1544 if _len_guards(M):
1545 return np.ones(M)
1546 M, needs_trunc = _extend(M, sym)
1548 # our width is the full bandwidth
1549 width = width / 2
1550 # to match the old version
1551 width = width / 2
1552 m = np.arange(M, dtype='d')
1553 H = np.zeros((2, M))
1554 H[0, 1:] = m[1:] * (M - m[1:]) / 2
1555 H[1, :] = ((M - 1 - 2 * m) / 2)**2 * np.cos(2 * np.pi * width)
1557 _, win = linalg.eig_banded(H, select='i', select_range=(M-1, M-1))
1558 win = win.ravel() / win.max()
1560 return _truncate(win, needs_trunc)
1563def cosine(M, sym=True):
1564 """Return a window with a simple cosine shape.
1566 Parameters
1567 ----------
1568 M : int
1569 Number of points in the output window. If zero or less, an empty
1570 array is returned.
1571 sym : bool, optional
1572 When True (default), generates a symmetric window, for use in filter
1573 design.
1574 When False, generates a periodic window, for use in spectral analysis.
1576 Returns
1577 -------
1578 w : ndarray
1579 The window, with the maximum value normalized to 1 (though the value 1
1580 does not appear if `M` is even and `sym` is True).
1582 Notes
1583 -----
1585 .. versionadded:: 0.13.0
1587 Examples
1588 --------
1589 Plot the window and its frequency response:
1591 >>> from scipy import signal
1592 >>> from scipy.fft import fft, fftshift
1593 >>> import matplotlib.pyplot as plt
1595 >>> window = signal.cosine(51)
1596 >>> plt.plot(window)
1597 >>> plt.title("Cosine window")
1598 >>> plt.ylabel("Amplitude")
1599 >>> plt.xlabel("Sample")
1601 >>> plt.figure()
1602 >>> A = fft(window, 2048) / (len(window)/2.0)
1603 >>> freq = np.linspace(-0.5, 0.5, len(A))
1604 >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max())))
1605 >>> plt.plot(freq, response)
1606 >>> plt.axis([-0.5, 0.5, -120, 0])
1607 >>> plt.title("Frequency response of the cosine window")
1608 >>> plt.ylabel("Normalized magnitude [dB]")
1609 >>> plt.xlabel("Normalized frequency [cycles per sample]")
1610 >>> plt.show()
1612 """
1613 if _len_guards(M):
1614 return np.ones(M)
1615 M, needs_trunc = _extend(M, sym)
1617 w = np.sin(np.pi / M * (np.arange(0, M) + .5))
1619 return _truncate(w, needs_trunc)
1622def exponential(M, center=None, tau=1., sym=True):
1623 r"""Return an exponential (or Poisson) window.
1625 Parameters
1626 ----------
1627 M : int
1628 Number of points in the output window. If zero or less, an empty
1629 array is returned.
1630 center : float, optional
1631 Parameter defining the center location of the window function.
1632 The default value if not given is ``center = (M-1) / 2``. This
1633 parameter must take its default value for symmetric windows.
1634 tau : float, optional
1635 Parameter defining the decay. For ``center = 0`` use
1636 ``tau = -(M-1) / ln(x)`` if ``x`` is the fraction of the window
1637 remaining at the end.
1638 sym : bool, optional
1639 When True (default), generates a symmetric window, for use in filter
1640 design.
1641 When False, generates a periodic window, for use in spectral analysis.
1643 Returns
1644 -------
1645 w : ndarray
1646 The window, with the maximum value normalized to 1 (though the value 1
1647 does not appear if `M` is even and `sym` is True).
1649 Notes
1650 -----
1651 The Exponential window is defined as
1653 .. math:: w(n) = e^{-|n-center| / \tau}
1655 References
1656 ----------
1657 S. Gade and H. Herlufsen, "Windows to FFT analysis (Part I)",
1658 Technical Review 3, Bruel & Kjaer, 1987.
1660 Examples
1661 --------
1662 Plot the symmetric window and its frequency response:
1664 >>> from scipy import signal
1665 >>> from scipy.fft import fft, fftshift
1666 >>> import matplotlib.pyplot as plt
1668 >>> M = 51
1669 >>> tau = 3.0
1670 >>> window = signal.exponential(M, tau=tau)
1671 >>> plt.plot(window)
1672 >>> plt.title("Exponential Window (tau=3.0)")
1673 >>> plt.ylabel("Amplitude")
1674 >>> plt.xlabel("Sample")
1676 >>> plt.figure()
1677 >>> A = fft(window, 2048) / (len(window)/2.0)
1678 >>> freq = np.linspace(-0.5, 0.5, len(A))
1679 >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max())))
1680 >>> plt.plot(freq, response)
1681 >>> plt.axis([-0.5, 0.5, -35, 0])
1682 >>> plt.title("Frequency response of the Exponential window (tau=3.0)")
1683 >>> plt.ylabel("Normalized magnitude [dB]")
1684 >>> plt.xlabel("Normalized frequency [cycles per sample]")
1686 This function can also generate non-symmetric windows:
1688 >>> tau2 = -(M-1) / np.log(0.01)
1689 >>> window2 = signal.exponential(M, 0, tau2, False)
1690 >>> plt.figure()
1691 >>> plt.plot(window2)
1692 >>> plt.ylabel("Amplitude")
1693 >>> plt.xlabel("Sample")
1694 """
1695 if sym and center is not None:
1696 raise ValueError("If sym==True, center must be None.")
1697 if _len_guards(M):
1698 return np.ones(M)
1699 M, needs_trunc = _extend(M, sym)
1701 if center is None:
1702 center = (M-1) / 2
1704 n = np.arange(0, M)
1705 w = np.exp(-np.abs(n-center) / tau)
1707 return _truncate(w, needs_trunc)
1710def dpss(M, NW, Kmax=None, sym=True, norm=None, return_ratios=False):
1711 """
1712 Compute the Discrete Prolate Spheroidal Sequences (DPSS).
1714 DPSS (or Slepian sequences) are often used in multitaper power spectral
1715 density estimation (see [1]_). The first window in the sequence can be
1716 used to maximize the energy concentration in the main lobe, and is also
1717 called the Slepian window.
1719 Parameters
1720 ----------
1721 M : int
1722 Window length.
1723 NW : float
1724 Standardized half bandwidth corresponding to ``2*NW = BW/f0 = BW*N*dt``
1725 where ``dt`` is taken as 1.
1726 Kmax : int | None, optional
1727 Number of DPSS windows to return (orders ``0`` through ``Kmax-1``).
1728 If None (default), return only a single window of shape ``(M,)``
1729 instead of an array of windows of shape ``(Kmax, M)``.
1730 sym : bool, optional
1731 When True (default), generates a symmetric window, for use in filter
1732 design.
1733 When False, generates a periodic window, for use in spectral analysis.
1734 norm : {2, 'approximate', 'subsample'} | None, optional
1735 If 'approximate' or 'subsample', then the windows are normalized by the
1736 maximum, and a correction scale-factor for even-length windows
1737 is applied either using ``M**2/(M**2+NW)`` ("approximate") or
1738 a FFT-based subsample shift ("subsample"), see Notes for details.
1739 If None, then "approximate" is used when ``Kmax=None`` and 2 otherwise
1740 (which uses the l2 norm).
1741 return_ratios : bool, optional
1742 If True, also return the concentration ratios in addition to the
1743 windows.
1745 Returns
1746 -------
1747 v : ndarray, shape (Kmax, N) or (N,)
1748 The DPSS windows. Will be 1D if `Kmax` is None.
1749 r : ndarray, shape (Kmax,) or float, optional
1750 The concentration ratios for the windows. Only returned if
1751 `return_ratios` evaluates to True. Will be 0D if `Kmax` is None.
1753 Notes
1754 -----
1755 This computation uses the tridiagonal eigenvector formulation given
1756 in [2]_.
1758 The default normalization for ``Kmax=None``, i.e. window-generation mode,
1759 simply using the l-infinity norm would create a window with two unity
1760 values, which creates slight normalization differences between even and odd
1761 orders. The approximate correction of ``M**2/float(M**2+NW)`` for even
1762 sample numbers is used to counteract this effect (see Examples below).
1764 For very long signals (e.g., 1e6 elements), it can be useful to compute
1765 windows orders of magnitude shorter and use interpolation (e.g.,
1766 `scipy.interpolate.interp1d`) to obtain tapers of length `M`,
1767 but this in general will not preserve orthogonality between the tapers.
1769 .. versionadded:: 1.1
1771 References
1772 ----------
1773 .. [1] Percival DB, Walden WT. Spectral Analysis for Physical Applications:
1774 Multitaper and Conventional Univariate Techniques.
1775 Cambridge University Press; 1993.
1776 .. [2] Slepian, D. Prolate spheroidal wave functions, Fourier analysis, and
1777 uncertainty V: The discrete case. Bell System Technical Journal,
1778 Volume 57 (1978), 1371430.
1779 .. [3] Kaiser, JF, Schafer RW. On the Use of the I0-Sinh Window for
1780 Spectrum Analysis. IEEE Transactions on Acoustics, Speech and
1781 Signal Processing. ASSP-28 (1): 105-107; 1980.
1783 Examples
1784 --------
1785 We can compare the window to `kaiser`, which was invented as an alternative
1786 that was easier to calculate [3]_ (example adapted from
1787 `here <https://ccrma.stanford.edu/~jos/sasp/Kaiser_DPSS_Windows_Compared.html>`_):
1789 >>> import numpy as np
1790 >>> import matplotlib.pyplot as plt
1791 >>> from scipy.signal import windows, freqz
1792 >>> N = 51
1793 >>> fig, axes = plt.subplots(3, 2, figsize=(5, 7))
1794 >>> for ai, alpha in enumerate((1, 3, 5)):
1795 ... win_dpss = windows.dpss(N, alpha)
1796 ... beta = alpha*np.pi
1797 ... win_kaiser = windows.kaiser(N, beta)
1798 ... for win, c in ((win_dpss, 'k'), (win_kaiser, 'r')):
1799 ... win /= win.sum()
1800 ... axes[ai, 0].plot(win, color=c, lw=1.)
1801 ... axes[ai, 0].set(xlim=[0, N-1], title=r'$\\alpha$ = %s' % alpha,
1802 ... ylabel='Amplitude')
1803 ... w, h = freqz(win)
1804 ... axes[ai, 1].plot(w, 20 * np.log10(np.abs(h)), color=c, lw=1.)
1805 ... axes[ai, 1].set(xlim=[0, np.pi],
1806 ... title=r'$\\beta$ = %0.2f' % beta,
1807 ... ylabel='Magnitude (dB)')
1808 >>> for ax in axes.ravel():
1809 ... ax.grid(True)
1810 >>> axes[2, 1].legend(['DPSS', 'Kaiser'])
1811 >>> fig.tight_layout()
1812 >>> plt.show()
1814 And here are examples of the first four windows, along with their
1815 concentration ratios:
1817 >>> M = 512
1818 >>> NW = 2.5
1819 >>> win, eigvals = windows.dpss(M, NW, 4, return_ratios=True)
1820 >>> fig, ax = plt.subplots(1)
1821 >>> ax.plot(win.T, linewidth=1.)
1822 >>> ax.set(xlim=[0, M-1], ylim=[-0.1, 0.1], xlabel='Samples',
1823 ... title='DPSS, M=%d, NW=%0.1f' % (M, NW))
1824 >>> ax.legend(['win[%d] (%0.4f)' % (ii, ratio)
1825 ... for ii, ratio in enumerate(eigvals)])
1826 >>> fig.tight_layout()
1827 >>> plt.show()
1829 Using a standard :math:`l_{\\infty}` norm would produce two unity values
1830 for even `M`, but only one unity value for odd `M`. This produces uneven
1831 window power that can be counteracted by the approximate correction
1832 ``M**2/float(M**2+NW)``, which can be selected by using
1833 ``norm='approximate'`` (which is the same as ``norm=None`` when
1834 ``Kmax=None``, as is the case here). Alternatively, the slower
1835 ``norm='subsample'`` can be used, which uses subsample shifting in the
1836 frequency domain (FFT) to compute the correction:
1838 >>> Ms = np.arange(1, 41)
1839 >>> factors = (50, 20, 10, 5, 2.0001)
1840 >>> energy = np.empty((3, len(Ms), len(factors)))
1841 >>> for mi, M in enumerate(Ms):
1842 ... for fi, factor in enumerate(factors):
1843 ... NW = M / float(factor)
1844 ... # Corrected using empirical approximation (default)
1845 ... win = windows.dpss(M, NW)
1846 ... energy[0, mi, fi] = np.sum(win ** 2) / np.sqrt(M)
1847 ... # Corrected using subsample shifting
1848 ... win = windows.dpss(M, NW, norm='subsample')
1849 ... energy[1, mi, fi] = np.sum(win ** 2) / np.sqrt(M)
1850 ... # Uncorrected (using l-infinity norm)
1851 ... win /= win.max()
1852 ... energy[2, mi, fi] = np.sum(win ** 2) / np.sqrt(M)
1853 >>> fig, ax = plt.subplots(1)
1854 >>> hs = ax.plot(Ms, energy[2], '-o', markersize=4,
1855 ... markeredgecolor='none')
1856 >>> leg = [hs[-1]]
1857 >>> for hi, hh in enumerate(hs):
1858 ... h1 = ax.plot(Ms, energy[0, :, hi], '-o', markersize=4,
1859 ... color=hh.get_color(), markeredgecolor='none',
1860 ... alpha=0.66)
1861 ... h2 = ax.plot(Ms, energy[1, :, hi], '-o', markersize=4,
1862 ... color=hh.get_color(), markeredgecolor='none',
1863 ... alpha=0.33)
1864 ... if hi == len(hs) - 1:
1865 ... leg.insert(0, h1[0])
1866 ... leg.insert(0, h2[0])
1867 >>> ax.set(xlabel='M (samples)', ylabel=r'Power / $\\sqrt{M}$')
1868 >>> ax.legend(leg, ['Uncorrected', r'Corrected: $\\frac{M^2}{M^2+NW}$',
1869 ... 'Corrected (subsample)'])
1870 >>> fig.tight_layout()
1872 """ # noqa: E501
1873 if _len_guards(M):
1874 return np.ones(M)
1875 if norm is None:
1876 norm = 'approximate' if Kmax is None else 2
1877 known_norms = (2, 'approximate', 'subsample')
1878 if norm not in known_norms:
1879 raise ValueError('norm must be one of %s, got %s'
1880 % (known_norms, norm))
1881 if Kmax is None:
1882 singleton = True
1883 Kmax = 1
1884 else:
1885 singleton = False
1886 Kmax = operator.index(Kmax)
1887 if not 0 < Kmax <= M:
1888 raise ValueError('Kmax must be greater than 0 and less than M')
1889 if NW >= M/2.:
1890 raise ValueError('NW must be less than M/2.')
1891 if NW <= 0:
1892 raise ValueError('NW must be positive')
1893 M, needs_trunc = _extend(M, sym)
1894 W = float(NW) / M
1895 nidx = np.arange(M)
1897 # Here we want to set up an optimization problem to find a sequence
1898 # whose energy is maximally concentrated within band [-W,W].
1899 # Thus, the measure lambda(T,W) is the ratio between the energy within
1900 # that band, and the total energy. This leads to the eigen-system
1901 # (A - (l1)I)v = 0, where the eigenvector corresponding to the largest
1902 # eigenvalue is the sequence with maximally concentrated energy. The
1903 # collection of eigenvectors of this system are called Slepian
1904 # sequences, or discrete prolate spheroidal sequences (DPSS). Only the
1905 # first K, K = 2NW/dt orders of DPSS will exhibit good spectral
1906 # concentration
1907 # [see https://en.wikipedia.org/wiki/Spectral_concentration_problem]
1909 # Here we set up an alternative symmetric tri-diagonal eigenvalue
1910 # problem such that
1911 # (B - (l2)I)v = 0, and v are our DPSS (but eigenvalues l2 != l1)
1912 # the main diagonal = ([N-1-2*t]/2)**2 cos(2PIW), t=[0,1,2,...,N-1]
1913 # and the first off-diagonal = t(N-t)/2, t=[1,2,...,N-1]
1914 # [see Percival and Walden, 1993]
1915 d = ((M - 1 - 2 * nidx) / 2.) ** 2 * np.cos(2 * np.pi * W)
1916 e = nidx[1:] * (M - nidx[1:]) / 2.
1918 # only calculate the highest Kmax eigenvalues
1919 w, windows = linalg.eigh_tridiagonal(
1920 d, e, select='i', select_range=(M - Kmax, M - 1))
1921 w = w[::-1]
1922 windows = windows[:, ::-1].T
1924 # By convention (Percival and Walden, 1993 pg 379)
1925 # * symmetric tapers (k=0,2,4,...) should have a positive average.
1926 fix_even = (windows[::2].sum(axis=1) < 0)
1927 for i, f in enumerate(fix_even):
1928 if f:
1929 windows[2 * i] *= -1
1930 # * antisymmetric tapers should begin with a positive lobe
1931 # (this depends on the definition of "lobe", here we'll take the first
1932 # point above the numerical noise, which should be good enough for
1933 # sufficiently smooth functions, and more robust than relying on an
1934 # algorithm that uses max(abs(w)), which is susceptible to numerical
1935 # noise problems)
1936 thresh = max(1e-7, 1. / M)
1937 for i, w in enumerate(windows[1::2]):
1938 if w[w * w > thresh][0] < 0:
1939 windows[2 * i + 1] *= -1
1941 # Now find the eigenvalues of the original spectral concentration problem
1942 # Use the autocorr sequence technique from Percival and Walden, 1993 pg 390
1943 if return_ratios:
1944 dpss_rxx = _fftautocorr(windows)
1945 r = 4 * W * np.sinc(2 * W * nidx)
1946 r[0] = 2 * W
1947 ratios = np.dot(dpss_rxx, r)
1948 if singleton:
1949 ratios = ratios[0]
1950 # Deal with sym and Kmax=None
1951 if norm != 2:
1952 windows /= windows.max()
1953 if M % 2 == 0:
1954 if norm == 'approximate':
1955 correction = M**2 / float(M**2 + NW)
1956 else:
1957 s = sp_fft.rfft(windows[0])
1958 shift = -(1 - 1./M) * np.arange(1, M//2 + 1)
1959 s[1:] *= 2 * np.exp(-1j * np.pi * shift)
1960 correction = M / s.real.sum()
1961 windows *= correction
1962 # else we're already l2 normed, so do nothing
1963 if needs_trunc:
1964 windows = windows[:, :-1]
1965 if singleton:
1966 windows = windows[0]
1967 return (windows, ratios) if return_ratios else windows
1970def _fftautocorr(x):
1971 """Compute the autocorrelation of a real array and crop the result."""
1972 N = x.shape[-1]
1973 use_N = sp_fft.next_fast_len(2*N-1)
1974 x_fft = sp_fft.rfft(x, use_N, axis=-1)
1975 cxy = sp_fft.irfft(x_fft * x_fft.conj(), n=use_N)[:, :N]
1976 # Or equivalently (but in most cases slower):
1977 # cxy = np.array([np.convolve(xx, yy[::-1], mode='full')
1978 # for xx, yy in zip(x, x)])[:, N-1:2*N-1]
1979 return cxy
1982_win_equiv_raw = {
1983 ('barthann', 'brthan', 'bth'): (barthann, False),
1984 ('bartlett', 'bart', 'brt'): (bartlett, False),
1985 ('blackman', 'black', 'blk'): (blackman, False),
1986 ('blackmanharris', 'blackharr', 'bkh'): (blackmanharris, False),
1987 ('bohman', 'bman', 'bmn'): (bohman, False),
1988 ('boxcar', 'box', 'ones',
1989 'rect', 'rectangular'): (boxcar, False),
1990 ('chebwin', 'cheb'): (chebwin, True),
1991 ('cosine', 'halfcosine'): (cosine, False),
1992 ('exponential', 'poisson'): (exponential, True),
1993 ('flattop', 'flat', 'flt'): (flattop, False),
1994 ('gaussian', 'gauss', 'gss'): (gaussian, True),
1995 ('general gaussian', 'general_gaussian',
1996 'general gauss', 'general_gauss', 'ggs'): (general_gaussian, True),
1997 ('hamming', 'hamm', 'ham'): (hamming, False),
1998 ('hanning', 'hann', 'han'): (hann, False),
1999 ('kaiser', 'ksr'): (kaiser, True),
2000 ('nuttall', 'nutl', 'nut'): (nuttall, False),
2001 ('parzen', 'parz', 'par'): (parzen, False),
2002 ('slepian', 'slep', 'optimal', 'dpss', 'dss'): (slepian, True),
2003 ('triangle', 'triang', 'tri'): (triang, False),
2004 ('tukey', 'tuk'): (tukey, True),
2005}
2007# Fill dict with all valid window name strings
2008_win_equiv = {}
2009for k, v in _win_equiv_raw.items():
2010 for key in k:
2011 _win_equiv[key] = v[0]
2013# Keep track of which windows need additional parameters
2014_needs_param = set()
2015for k, v in _win_equiv_raw.items():
2016 if v[1]:
2017 _needs_param.update(k)
2020def get_window(window, Nx, fftbins=True):
2021 """
2022 Return a window of a given length and type.
2024 Parameters
2025 ----------
2026 window : string, float, or tuple
2027 The type of window to create. See below for more details.
2028 Nx : int
2029 The number of samples in the window.
2030 fftbins : bool, optional
2031 If True (default), create a "periodic" window, ready to use with
2032 `ifftshift` and be multiplied by the result of an FFT (see also
2033 :func:`~scipy.fft.fftfreq`).
2034 If False, create a "symmetric" window, for use in filter design.
2036 Returns
2037 -------
2038 get_window : ndarray
2039 Returns a window of length `Nx` and type `window`
2041 Notes
2042 -----
2043 Window types:
2045 - `~scipy.signal.windows.boxcar`
2046 - `~scipy.signal.windows.triang`
2047 - `~scipy.signal.windows.blackman`
2048 - `~scipy.signal.windows.hamming`
2049 - `~scipy.signal.windows.hann`
2050 - `~scipy.signal.windows.bartlett`
2051 - `~scipy.signal.windows.flattop`
2052 - `~scipy.signal.windows.parzen`
2053 - `~scipy.signal.windows.bohman`
2054 - `~scipy.signal.windows.blackmanharris`
2055 - `~scipy.signal.windows.nuttall`
2056 - `~scipy.signal.windows.barthann`
2057 - `~scipy.signal.windows.kaiser` (needs beta)
2058 - `~scipy.signal.windows.gaussian` (needs standard deviation)
2059 - `~scipy.signal.windows.general_gaussian` (needs power, width)
2060 - `~scipy.signal.windows.slepian` (needs width)
2061 - `~scipy.signal.windows.dpss` (needs normalized half-bandwidth)
2062 - `~scipy.signal.windows.chebwin` (needs attenuation)
2063 - `~scipy.signal.windows.exponential` (needs decay scale)
2064 - `~scipy.signal.windows.tukey` (needs taper fraction)
2066 If the window requires no parameters, then `window` can be a string.
2068 If the window requires parameters, then `window` must be a tuple
2069 with the first argument the string name of the window, and the next
2070 arguments the needed parameters.
2072 If `window` is a floating point number, it is interpreted as the beta
2073 parameter of the `~scipy.signal.windows.kaiser` window.
2075 Each of the window types listed above is also the name of
2076 a function that can be called directly to create a window of
2077 that type.
2079 Examples
2080 --------
2081 >>> from scipy import signal
2082 >>> signal.get_window('triang', 7)
2083 array([ 0.125, 0.375, 0.625, 0.875, 0.875, 0.625, 0.375])
2084 >>> signal.get_window(('kaiser', 4.0), 9)
2085 array([ 0.08848053, 0.29425961, 0.56437221, 0.82160913, 0.97885093,
2086 0.97885093, 0.82160913, 0.56437221, 0.29425961])
2087 >>> signal.get_window(4.0, 9)
2088 array([ 0.08848053, 0.29425961, 0.56437221, 0.82160913, 0.97885093,
2089 0.97885093, 0.82160913, 0.56437221, 0.29425961])
2091 """
2092 sym = not fftbins
2093 try:
2094 beta = float(window)
2095 except (TypeError, ValueError):
2096 args = ()
2097 if isinstance(window, tuple):
2098 winstr = window[0]
2099 if len(window) > 1:
2100 args = window[1:]
2101 elif isinstance(window, str):
2102 if window in _needs_param:
2103 raise ValueError("The '" + window + "' window needs one or "
2104 "more parameters -- pass a tuple.")
2105 else:
2106 winstr = window
2107 else:
2108 raise ValueError("%s as window type is not supported." %
2109 str(type(window)))
2111 try:
2112 winfunc = _win_equiv[winstr]
2113 except KeyError:
2114 raise ValueError("Unknown window type.")
2116 params = (Nx,) + args + (sym,)
2117 else:
2118 winfunc = kaiser
2119 params = (Nx, beta, sym)
2121 return winfunc(*params)