0
# Window Functions
1
2
Comprehensive collection of window functions for signal processing applications. Windows are used to reduce spectral leakage in Fourier analysis, control sidelobe levels, and provide different trade-offs between main lobe width and sidelobe suppression.
3
4
## Capabilities
5
6
### Window Creation and Management
7
8
High-level interface for creating and managing window functions with automatic parameter validation.
9
10
```python { .api }
11
def create_window(N, name=None, **kargs):
12
"""
13
Create window function with specified parameters.
14
15
Parameters:
16
- N: int, window length
17
- name: str, window function name
18
- **kargs: dict, window-specific parameters
19
20
Returns:
21
array: Window function values
22
"""
23
24
class Window(N, name=None, **kargs):
25
"""
26
Window function generator and analyzer.
27
28
Parameters:
29
- N: int, window length
30
- name: str, window type ('hamming', 'hanning', 'kaiser', etc.)
31
- **kargs: dict, window parameters (beta, alpha, etc.)
32
33
Methods:
34
- plot(): visualize window and its frequency response
35
- info(): display window properties
36
"""
37
38
def enbw(data):
39
"""
40
Calculate equivalent noise bandwidth of window function.
41
42
Parameters:
43
- data: array-like, window function values
44
45
Returns:
46
float: Equivalent noise bandwidth (normalized)
47
"""
48
49
def window_visu(N=51, name="hamming", **kargs):
50
"""
51
Visualize window function and its frequency response.
52
53
Parameters:
54
- N: int, window length
55
- name: str, window function name
56
- **kargs: dict, window parameters
57
58
Returns:
59
None: displays plots directly
60
"""
61
```
62
63
### Common Window Functions
64
65
Standard window functions commonly used in signal processing applications.
66
67
```python { .api }
68
def window_rectangle(N):
69
"""
70
Rectangular (boxcar) window.
71
72
Parameters:
73
- N: int, window length
74
75
Returns:
76
array: Rectangular window values
77
"""
78
79
def window_hamming(N):
80
"""
81
Hamming window with optimized coefficients.
82
83
Parameters:
84
- N: int, window length
85
86
Returns:
87
array: Hamming window values
88
"""
89
90
def window_hann(N):
91
"""
92
Hann (Hanning) window - raised cosine.
93
94
Parameters:
95
- N: int, window length
96
97
Returns:
98
array: Hann window values
99
"""
100
101
def window_bartlett(N):
102
"""
103
Bartlett (triangular) window.
104
105
Parameters:
106
- N: int, window length
107
108
Returns:
109
array: Bartlett window values
110
"""
111
112
def window_blackman(N, alpha=0.16):
113
"""
114
Blackman window with adjustable parameter.
115
116
Parameters:
117
- N: int, window length
118
- alpha: float, window parameter (0.16 for standard Blackman)
119
120
Returns:
121
array: Blackman window values
122
"""
123
124
def window_kaiser(N, beta=8.6):
125
"""
126
Kaiser window using modified Bessel function.
127
128
Parameters:
129
- N: int, window length
130
- beta: float, shape parameter (higher = more suppression)
131
132
Returns:
133
array: Kaiser window values
134
"""
135
```
136
137
### Specialized Window Functions
138
139
Advanced window functions for specific applications and requirements.
140
141
```python { .api }
142
def window_gaussian(N, alpha=2.5):
143
"""
144
Gaussian window for smooth spectral characteristics.
145
146
Parameters:
147
- N: int, window length
148
- alpha: float, shape parameter (higher = narrower window)
149
150
Returns:
151
array: Gaussian window values
152
"""
153
154
def window_chebwin(N, attenuation=50):
155
"""
156
Chebyshev window with specified sidelobe attenuation.
157
158
Parameters:
159
- N: int, window length
160
- attenuation: float, sidelobe attenuation in dB
161
162
Returns:
163
array: Chebyshev window values
164
"""
165
166
def window_taylor(N, nbar=4, sll=-30):
167
"""
168
Taylor window for array processing applications.
169
170
Parameters:
171
- N: int, window length
172
- nbar: int, number of nearly equal sidelobes
173
- sll: float, sidelobe level in dB
174
175
Returns:
176
array: Taylor window values
177
"""
178
179
def window_flattop(N, mode="symmetric", precision=None):
180
"""
181
Flat-top window for amplitude measurements.
182
183
Parameters:
184
- N: int, window length
185
- mode: str, symmetry mode ('symmetric', 'periodic')
186
- precision: str, precision level (None, 'octave')
187
188
Returns:
189
array: Flat-top window values
190
"""
191
192
def window_tukey(N, r=0.5):
193
"""
194
Tukey (tapered cosine) window.
195
196
Parameters:
197
- N: int, window length
198
- r: float, taper ratio (0=rectangular, 1=Hann)
199
200
Returns:
201
array: Tukey window values
202
"""
203
```
204
205
### Extended Window Collection
206
207
Additional window functions for specialized applications.
208
209
```python { .api }
210
def window_cosine(N):
211
"""
212
Simple cosine window.
213
214
Parameters:
215
- N: int, window length
216
217
Returns:
218
array: Cosine window values
219
"""
220
221
def window_lanczos(N):
222
"""
223
Lanczos window (sinc function).
224
225
Parameters:
226
- N: int, window length
227
228
Returns:
229
array: Lanczos window values
230
"""
231
232
def window_bartlett_hann(N):
233
"""
234
Bartlett-Hann window (hybrid design).
235
236
Parameters:
237
- N: int, window length
238
239
Returns:
240
array: Bartlett-Hann window values
241
"""
242
243
def window_nuttall(N):
244
"""
245
Nuttall window (4-term Blackman-Harris).
246
247
Parameters:
248
- N: int, window length
249
250
Returns:
251
array: Nuttall window values
252
"""
253
254
def window_blackman_nuttall(N):
255
"""
256
Blackman-Nuttall window.
257
258
Parameters:
259
- N: int, window length
260
261
Returns:
262
array: Blackman-Nuttall window values
263
"""
264
265
def window_blackman_harris(N):
266
"""
267
Blackman-Harris window for low sidelobes.
268
269
Parameters:
270
- N: int, window length
271
272
Returns:
273
array: Blackman-Harris window values
274
"""
275
276
def window_bohman(N):
277
"""
278
Bohman window (convolution of triangular functions).
279
280
Parameters:
281
- N: int, window length
282
283
Returns:
284
array: Bohman window values
285
"""
286
287
def window_parzen(N):
288
"""
289
Parzen window (4th-order B-spline).
290
291
Parameters:
292
- N: int, window length
293
294
Returns:
295
array: Parzen window values
296
"""
297
```
298
299
### Probability-Based Windows
300
301
Window functions based on probability density functions.
302
303
```python { .api }
304
def window_riesz(N):
305
"""
306
Riesz window.
307
308
Parameters:
309
- N: int, window length
310
311
Returns:
312
array: Riesz window values
313
"""
314
315
def window_riemann(N):
316
"""
317
Riemann window.
318
319
Parameters:
320
- N: int, window length
321
322
Returns:
323
array: Riemann window values
324
"""
325
326
def window_poisson(N, alpha=2):
327
"""
328
Poisson window (exponential).
329
330
Parameters:
331
- N: int, window length
332
- alpha: float, decay parameter
333
334
Returns:
335
array: Poisson window values
336
"""
337
338
def window_poisson_hanning(N, alpha=2):
339
"""
340
Poisson-Hanning hybrid window.
341
342
Parameters:
343
- N: int, window length
344
- alpha: float, Poisson parameter
345
346
Returns:
347
array: Poisson-Hanning window values
348
"""
349
350
def window_cauchy(N, alpha=3):
351
"""
352
Cauchy window (Lorentzian).
353
354
Parameters:
355
- N: int, window length
356
- alpha: float, shape parameter
357
358
Returns:
359
array: Cauchy window values
360
"""
361
```
362
363
## Usage Examples
364
365
### Window Comparison and Analysis
366
367
```python
368
import spectrum
369
import numpy as np
370
import matplotlib.pyplot as plt
371
372
# Compare common window functions
373
N = 64
374
windows = {
375
'Rectangular': spectrum.window_rectangle(N),
376
'Hamming': spectrum.window_hamming(N),
377
'Hanning': spectrum.window_hann(N),
378
'Blackman': spectrum.window_blackman(N),
379
'Kaiser (β=8.6)': spectrum.window_kaiser(N, beta=8.6),
380
'Gaussian': spectrum.window_gaussian(N, alpha=2.5)
381
}
382
383
# Plot window shapes
384
plt.figure(figsize=(15, 10))
385
386
plt.subplot(2, 2, 1)
387
for name, window in windows.items():
388
plt.plot(window, label=name, linewidth=2)
389
plt.title('Window Functions (Time Domain)')
390
plt.xlabel('Sample')
391
plt.ylabel('Amplitude')
392
plt.legend()
393
plt.grid(True)
394
395
# Plot frequency responses
396
plt.subplot(2, 2, 2)
397
NFFT = 512
398
freqs = np.linspace(0, 0.5, NFFT//2)
399
400
for name, window in windows.items():
401
# Zero-pad and compute FFT
402
windowed_padded = np.concatenate([window, np.zeros(NFFT - N)])
403
W = np.fft.fft(windowed_padded)
404
W_mag = 20 * np.log10(np.abs(W[:NFFT//2]) / np.max(np.abs(W)))
405
plt.plot(freqs, W_mag, label=name, linewidth=2)
406
407
plt.title('Window Frequency Responses')
408
plt.xlabel('Normalized Frequency')
409
plt.ylabel('Magnitude (dB)')
410
plt.ylim(-120, 10)
411
plt.legend()
412
plt.grid(True)
413
414
# Compute and display window properties
415
plt.subplot(2, 2, 3)
416
properties = {}
417
for name, window in windows.items():
418
enbw_val = spectrum.enbw(window)
419
coherent_gain = np.mean(window)
420
processing_gain = np.sum(window**2) / len(window)
421
properties[name] = [enbw_val, coherent_gain, processing_gain]
422
423
prop_names = ['ENBW', 'Coherent Gain', 'Processing Gain']
424
x_pos = np.arange(len(windows))
425
426
for i, prop in enumerate(prop_names):
427
values = [properties[name][i] for name in windows.keys()]
428
plt.subplot(2, 2, 3)
429
if i == 0: # ENBW
430
plt.bar(x_pos, values, alpha=0.7, label=prop)
431
plt.xticks(x_pos, list(windows.keys()), rotation=45)
432
plt.ylabel('ENBW')
433
plt.title('Equivalent Noise Bandwidth')
434
plt.grid(True)
435
436
plt.subplot(2, 2, 4)
437
# Detailed properties table
438
props_text = "Window Properties:\n\n"
439
for name in windows.keys():
440
enbw_val, cg, pg = properties[name]
441
props_text += f"{name}:\n"
442
props_text += f" ENBW: {enbw_val:.3f}\n"
443
props_text += f" Coherent Gain: {cg:.3f}\n"
444
props_text += f" Processing Gain: {pg:.3f}\n\n"
445
446
plt.text(0.05, 0.95, props_text, transform=plt.gca().transAxes,
447
fontfamily='monospace', fontsize=8, verticalalignment='top')
448
plt.axis('off')
449
450
plt.tight_layout()
451
plt.show()
452
```
453
454
### Kaiser Window Parameter Study
455
456
```python
457
import spectrum
458
import numpy as np
459
import matplotlib.pyplot as plt
460
461
# Study Kaiser window for different β values
462
N = 128
463
beta_values = [0, 2, 5, 8.6, 12, 20]
464
colors = plt.cm.viridis(np.linspace(0, 1, len(beta_values)))
465
466
plt.figure(figsize=(15, 8))
467
468
# Time domain
469
plt.subplot(1, 3, 1)
470
for i, beta in enumerate(beta_values):
471
kaiser_win = spectrum.window_kaiser(N, beta=beta)
472
plt.plot(kaiser_win, color=colors[i], linewidth=2,
473
label=f'β = {beta}')
474
plt.title('Kaiser Windows - Time Domain')
475
plt.xlabel('Sample')
476
plt.ylabel('Amplitude')
477
plt.legend()
478
plt.grid(True)
479
480
# Frequency domain
481
plt.subplot(1, 3, 2)
482
NFFT = 1024
483
freqs = np.linspace(0, 0.5, NFFT//2)
484
485
for i, beta in enumerate(beta_values):
486
kaiser_win = spectrum.window_kaiser(N, beta=beta)
487
# Zero-pad and compute FFT
488
padded = np.concatenate([kaiser_win, np.zeros(NFFT - N)])
489
W = np.fft.fft(padded)
490
W_mag = 20 * np.log10(np.abs(W[:NFFT//2]) / np.max(np.abs(W)))
491
plt.plot(freqs, W_mag, color=colors[i], linewidth=2,
492
label=f'β = {beta}')
493
494
plt.title('Kaiser Windows - Frequency Domain')
495
plt.xlabel('Normalized Frequency')
496
plt.ylabel('Magnitude (dB)')
497
plt.ylim(-140, 10)
498
plt.legend()
499
plt.grid(True)
500
501
# Properties vs β
502
plt.subplot(1, 3, 3)
503
beta_range = np.linspace(0, 20, 50)
504
enbw_values = []
505
main_lobe_width = []
506
peak_sidelobe = []
507
508
for beta in beta_range:
509
kaiser_win = spectrum.window_kaiser(N, beta=beta)
510
enbw_val = spectrum.enbw(kaiser_win)
511
enbw_values.append(enbw_val)
512
513
# Compute frequency response for main lobe and sidelobe analysis
514
padded = np.concatenate([kaiser_win, np.zeros(1024 - N)])
515
W = np.fft.fft(padded)
516
W_mag = np.abs(W[:512])
517
W_mag_db = 20 * np.log10(W_mag / np.max(W_mag))
518
519
# Find main lobe width (3dB points)
520
peak_idx = np.argmax(W_mag)
521
main_lobe_3db = np.where(W_mag_db >= -3)[0]
522
main_lobe_width.append(len(main_lobe_3db))
523
524
# Find peak sidelobe level
525
# Find first null after main lobe
526
first_null = peak_idx + np.argmin(W_mag[peak_idx:peak_idx+50])
527
if first_null + 10 < len(W_mag_db):
528
sidelobe_region = W_mag_db[first_null+5:]
529
peak_sidelobe.append(np.max(sidelobe_region))
530
else:
531
peak_sidelobe.append(-100)
532
533
plt.plot(beta_range, enbw_values, 'b-', linewidth=2, label='ENBW')
534
plt.xlabel('Kaiser β Parameter')
535
plt.ylabel('ENBW')
536
plt.title('Kaiser Window Properties vs β')
537
plt.grid(True)
538
539
# Add second y-axis for sidelobe level
540
ax2 = plt.gca().twinx()
541
ax2.plot(beta_range, peak_sidelobe, 'r--', linewidth=2, label='Peak Sidelobe (dB)')
542
ax2.set_ylabel('Peak Sidelobe Level (dB)')
543
ax2.set_ylim(-120, -20)
544
545
# Combined legend
546
lines1, labels1 = plt.gca().get_legend_handles_labels()
547
lines2, labels2 = ax2.get_legend_handles_labels()
548
plt.gca().legend(lines1 + lines2, labels1 + labels2, loc='center right')
549
550
plt.tight_layout()
551
plt.show()
552
553
# Print some specific values
554
print("Kaiser Window Design Guidelines:")
555
print("β = 0: Rectangular window")
556
print("β = 5: Good compromise (≈ Hamming)")
557
print("β = 8.6: Similar to Blackman")
558
print("β = 12: High sidelobe suppression")
559
print("β > 15: Very high suppression, wide main lobe")
560
```
561
562
### Window Selection for Different Applications
563
564
```python
565
import spectrum
566
import numpy as np
567
import matplotlib.pyplot as plt
568
569
def demonstrate_windowing_effects(signal, windows_dict, title=""):
570
"""Demonstrate the effect of different windows on spectral analysis."""
571
572
plt.figure(figsize=(15, 12))
573
574
# Plot original signal
575
plt.subplot(3, 3, 1)
576
plt.plot(signal)
577
plt.title(f'{title} - Time Domain')
578
plt.xlabel('Sample')
579
plt.ylabel('Amplitude')
580
plt.grid(True)
581
582
# Compute and plot windowed signals and spectra
583
for i, (window_name, window_func) in enumerate(windows_dict.items()):
584
# Apply window
585
windowed_signal = signal * window_func
586
587
# Compute FFT
588
N_fft = 1024
589
fft_result = np.fft.fft(windowed_signal, N_fft)
590
freqs = np.linspace(0, 0.5, N_fft//2)
591
psd = np.abs(fft_result[:N_fft//2])**2
592
psd_db = 10 * np.log10(psd / np.max(psd))
593
594
# Plot windowed signal
595
plt.subplot(3, 3, 2 + i)
596
plt.plot(windowed_signal, 'b-', alpha=0.7)
597
plt.plot(window_func, 'r--', alpha=0.7, label='Window')
598
plt.title(f'{window_name} Windowed')
599
plt.xlabel('Sample')
600
plt.grid(True)
601
if i == 0:
602
plt.legend()
603
604
# Plot spectrum
605
plt.subplot(3, 3, 6 + i)
606
plt.plot(freqs, psd_db, linewidth=2)
607
plt.title(f'{window_name} Spectrum')
608
plt.xlabel('Normalized Frequency')
609
plt.ylabel('PSD (dB)')
610
plt.ylim(-80, 5)
611
plt.grid(True)
612
613
plt.tight_layout()
614
plt.show()
615
616
# Test Case 1: Single sinusoid (spectral leakage)
617
N = 128
618
n = np.arange(N)
619
f = 0.1234 # Non-integer number of cycles
620
signal1 = np.sin(2 * np.pi * f * n)
621
622
windows1 = {
623
'Rectangular': spectrum.window_rectangle(N),
624
'Hamming': spectrum.window_hamming(N),
625
'Kaiser β=8.6': spectrum.window_kaiser(N, beta=8.6),
626
'Blackman': spectrum.window_blackman(N)
627
}
628
629
demonstrate_windowing_effects(signal1, windows1, "Single Sinusoid (Leakage Test)")
630
631
# Test Case 2: Two close sinusoids (resolution test)
632
f1, f2 = 0.2, 0.22 # Close frequencies
633
signal2 = np.sin(2*np.pi*f1*n) + np.sin(2*np.pi*f2*n)
634
635
windows2 = {
636
'Rectangular': spectrum.window_rectangle(N),
637
'Hanning': spectrum.window_hann(N),
638
'Flat-top': spectrum.window_flattop(N),
639
'Gaussian': spectrum.window_gaussian(N, alpha=2.5)
640
}
641
642
demonstrate_windowing_effects(signal2, windows2, "Two Close Sinusoids (Resolution Test)")
643
644
# Test Case 3: Amplitude measurement test
645
signal3 = 2.5 * np.sin(2*np.pi*0.1*n) + 1.8 * np.sin(2*np.pi*0.3*n)
646
647
windows3 = {
648
'Rectangular': spectrum.window_rectangle(N),
649
'Flat-top': spectrum.window_flattop(N),
650
'Kaiser β=12': spectrum.window_kaiser(N, beta=12),
651
'Nuttall': spectrum.window_nuttall(N)
652
}
653
654
demonstrate_windowing_effects(signal3, windows3, "Amplitude Measurement Test")
655
656
# Window selection guidelines
657
print("\n" + "="*60)
658
print("WINDOW SELECTION GUIDELINES")
659
print("="*60)
660
print("Application | Recommended Windows")
661
print("-" * 60)
662
print("General purpose | Hamming, Hanning")
663
print("Spectral analysis | Kaiser (β=8.6), Blackman")
664
print("Amplitude measurements | Flat-top, Kaiser (β=12)")
665
print("Frequency resolution | Rectangular, Tukey")
666
print("Sidelobe suppression | Chebyshev, Kaiser (β>10)")
667
print("Transient analysis | Gaussian, Hamming")
668
print("Array processing | Taylor, Chebyshev")
669
print("Low noise floor | Blackman-Harris, Nuttall")
670
```
671
672
### Custom Window Design
673
674
```python
675
import spectrum
676
import numpy as np
677
import matplotlib.pyplot as plt
678
679
def design_custom_window(N, target_sidelobe_db=-60):
680
"""Design custom Kaiser window for target sidelobe level."""
681
682
# Kaiser window design formula
683
if target_sidelobe_db > -21:
684
beta = 0
685
elif target_sidelobe_db >= -50:
686
beta = 0.5842 * (abs(target_sidelobe_db) - 21)**0.4 + 0.07886 * (abs(target_sidelobe_db) - 21)
687
else:
688
beta = 0.1102 * (abs(target_sidelobe_db) - 8.7)
689
690
return spectrum.window_kaiser(N, beta=beta), beta
691
692
def optimize_window_parameters():
693
"""Demonstrate window parameter optimization."""
694
695
N = 64
696
target_levels = [-40, -60, -80, -100]
697
698
plt.figure(figsize=(15, 10))
699
700
# Design windows for different sidelobe targets
701
plt.subplot(2, 2, 1)
702
for target_db in target_levels:
703
custom_window, beta_used = design_custom_window(N, target_db)
704
plt.plot(custom_window, label=f'Target: {target_db}dB (β={beta_used:.2f})', linewidth=2)
705
706
plt.title('Custom Kaiser Windows for Different Sidelobe Targets')
707
plt.xlabel('Sample')
708
plt.ylabel('Amplitude')
709
plt.legend()
710
plt.grid(True)
711
712
# Frequency responses
713
plt.subplot(2, 2, 2)
714
NFFT = 1024
715
freqs = np.linspace(0, 0.5, NFFT//2)
716
717
for target_db in target_levels:
718
custom_window, beta_used = design_custom_window(N, target_db)
719
padded = np.concatenate([custom_window, np.zeros(NFFT - N)])
720
W = np.fft.fft(padded)
721
W_mag_db = 20 * np.log10(np.abs(W[:NFFT//2]) / np.max(np.abs(W)))
722
plt.plot(freqs, W_mag_db, label=f'{target_db}dB target', linewidth=2)
723
724
plt.title('Frequency Responses of Custom Windows')
725
plt.xlabel('Normalized Frequency')
726
plt.ylabel('Magnitude (dB)')
727
plt.ylim(-120, 10)
728
plt.legend()
729
plt.grid(True)
730
731
# Parameter relationships
732
plt.subplot(2, 2, 3)
733
target_range = np.linspace(-20, -120, 100)
734
beta_values = []
735
enbw_values = []
736
737
for target in target_range:
738
window, beta = design_custom_window(N, target)
739
beta_values.append(beta)
740
enbw_values.append(spectrum.enbw(window))
741
742
plt.plot(target_range, beta_values, 'b-', linewidth=2, label='Kaiser β')
743
plt.xlabel('Target Sidelobe Level (dB)')
744
plt.ylabel('Kaiser β Parameter')
745
plt.title('Kaiser β vs Sidelobe Target')
746
plt.grid(True)
747
748
# ENBW vs sidelobe level
749
plt.subplot(2, 2, 4)
750
plt.plot(target_range, enbw_values, 'r-', linewidth=2)
751
plt.xlabel('Target Sidelobe Level (dB)')
752
plt.ylabel('Equivalent Noise Bandwidth')
753
plt.title('ENBW vs Sidelobe Level Trade-off')
754
plt.grid(True)
755
756
plt.tight_layout()
757
plt.show()
758
759
# Demonstrate window class usage
760
print("Using Window Class for Analysis:")
761
print("-" * 40)
762
763
# Create window object
764
N = 64
765
w = spectrum.Window(N, name='kaiser', beta=10.0)
766
767
# Get window properties
768
print(f"Window type: {w.name if hasattr(w, 'name') else 'Kaiser'}")
769
print(f"Window length: {N}")
770
print(f"ENBW: {spectrum.enbw(w.data if hasattr(w, 'data') else spectrum.window_kaiser(N, 10.0)):.4f}")
771
772
# Visualize multiple windows with the visualization function
773
print("\nGenerating window visualizations...")
774
spectrum.window_visu(N=64, name="hamming")
775
spectrum.window_visu(N=64, name="kaiser", beta=8.6)
776
777
# Run the optimization demonstration
778
optimize_window_parameters()
779
```