0
# Multi-Level Discrete Wavelet Transform
1
2
Multi-level wavelet decomposition and reconstruction providing hierarchical analysis with automatic or specified decomposition levels for comprehensive signal and image analysis.
3
4
## Capabilities
5
6
### 1D Multi-Level DWT
7
8
Hierarchical decomposition and reconstruction for one-dimensional signals.
9
10
```python { .api }
11
def wavedec(data, wavelet, mode: str = 'symmetric', level: int = None, axis: int = -1):
12
"""
13
Multi-level 1D discrete wavelet decomposition.
14
15
Parameters:
16
- data: Input 1D array or multi-dimensional array
17
- wavelet: Wavelet specification (string name, Wavelet object, or filter bank)
18
- mode: Signal extension mode for boundary handling
19
- level: Decomposition level (default: maximum possible level)
20
- axis: Axis along which to perform decomposition (default: -1, last axis)
21
22
Returns:
23
List [cAn, cDn, cDn-1, ..., cD1] where:
24
- cAn: Approximation coefficients at level n
25
- cDi: Detail coefficients at level i (from finest to coarsest)
26
"""
27
28
def waverec(coeffs, wavelet, mode: str = 'symmetric', axis: int = -1):
29
"""
30
Multi-level 1D discrete wavelet reconstruction.
31
32
Parameters:
33
- coeffs: Coefficient list from wavedec [cAn, cDn, ..., cD1]
34
- wavelet: Wavelet specification matching decomposition
35
- mode: Signal extension mode matching decomposition
36
- axis: Axis along which to perform reconstruction
37
38
Returns:
39
Reconstructed 1D signal
40
"""
41
```
42
43
#### Usage Examples
44
45
```python
46
import pywt
47
import numpy as np
48
import matplotlib.pyplot as plt
49
50
# Create test signal with multiple frequency components
51
t = np.linspace(0, 2, 2048)
52
signal = (np.sin(2 * np.pi * 1 * t) + # Low frequency
53
0.5 * np.sin(2 * np.pi * 10 * t) + # Medium frequency
54
0.3 * np.sin(2 * np.pi * 100 * t)) # High frequency
55
noise = 0.1 * np.random.randn(len(signal))
56
noisy_signal = signal + noise
57
58
# Multi-level decomposition
59
coeffs = pywt.wavedec(noisy_signal, 'db8', level=6)
60
print(f"Number of coefficient arrays: {len(coeffs)}")
61
print(f"Coefficient array lengths: {[len(c) for c in coeffs]}")
62
63
# Access approximation and detail coefficients
64
cA6 = coeffs[0] # Approximation at level 6 (coarsest)
65
cD6 = coeffs[1] # Detail at level 6 (coarsest detail)
66
cD5 = coeffs[2] # Detail at level 5
67
cD4 = coeffs[3] # Detail at level 4
68
cD3 = coeffs[4] # Detail at level 3
69
cD2 = coeffs[5] # Detail at level 2
70
cD1 = coeffs[6] # Detail at level 1 (finest detail)
71
72
# Perfect reconstruction
73
reconstructed = pywt.waverec(coeffs, 'db8')
74
print(f"Reconstruction error: {np.max(np.abs(noisy_signal - reconstructed))}")
75
76
# Selective reconstruction - remove high-frequency noise (cD1, cD2)
77
denoised_coeffs = coeffs.copy()
78
denoised_coeffs[-1][:] = 0 # Zero out cD1 (finest details)
79
denoised_coeffs[-2][:] = 0 # Zero out cD2 (second finest details)
80
denoised_signal = pywt.waverec(denoised_coeffs, 'db8')
81
82
# Visualization
83
fig, axes = plt.subplots(4, 2, figsize=(15, 12))
84
85
# Original signals
86
axes[0, 0].plot(t, signal, 'b-', label='Clean')
87
axes[0, 0].plot(t, noisy_signal, 'r-', alpha=0.7, label='Noisy')
88
axes[0, 0].set_title('Original Signals')
89
axes[0, 0].legend()
90
91
axes[0, 1].plot(t, denoised_signal, 'g-', label='Denoised')
92
axes[0, 1].plot(t, signal, 'b--', alpha=0.7, label='True Signal')
93
axes[0, 1].set_title('Denoising Result')
94
axes[0, 1].legend()
95
96
# Plot coefficients at different levels
97
for i, (coeff, title) in enumerate(zip(coeffs[1:],
98
['cD6 (Coarsest Detail)', 'cD5', 'cD4',
99
'cD3', 'cD2', 'cD1 (Finest Detail)'])):
100
row = (i // 2) + 1
101
col = i % 2
102
if row < 4:
103
axes[row, col].plot(coeff)
104
axes[row, col].set_title(title)
105
106
plt.tight_layout()
107
plt.show()
108
109
# Automatic vs manual level selection
110
max_level = pywt.dwt_max_level(len(noisy_signal), pywt.Wavelet('db8').dec_len)
111
print(f"Maximum possible decomposition level: {max_level}")
112
113
# Decompose with automatic level
114
coeffs_auto = pywt.wavedec(noisy_signal, 'db8')
115
print(f"Automatic decomposition levels: {len(coeffs_auto) - 1}")
116
```
117
118
### 2D Multi-Level DWT
119
120
Hierarchical decomposition and reconstruction for two-dimensional data such as images.
121
122
```python { .api }
123
def wavedec2(data, wavelet, mode: str = 'symmetric', level: int = None, axes=(-2, -1)):
124
"""
125
Multi-level 2D discrete wavelet decomposition.
126
127
Parameters:
128
- data: Input 2D array or multi-dimensional array
129
- wavelet: Wavelet specification
130
- mode: Signal extension mode for boundary handling
131
- level: Decomposition level (default: maximum possible level)
132
- axes: Pair of axes along which to perform 2D DWT (default: last two axes)
133
134
Returns:
135
List [cAn, (cHn, cVn, cDn), (cHn-1, cVn-1, cDn-1), ..., (cH1, cV1, cD1)] where:
136
- cAn: Approximation coefficients at level n
137
- (cHi, cVi, cDi): Horizontal, vertical, diagonal detail coefficients at level i
138
"""
139
140
def waverec2(coeffs, wavelet, mode: str = 'symmetric', axes=(-2, -1)):
141
"""
142
Multi-level 2D discrete wavelet reconstruction.
143
144
Parameters:
145
- coeffs: Coefficient list from wavedec2
146
- wavelet: Wavelet specification matching decomposition
147
- mode: Signal extension mode matching decomposition
148
- axes: Pair of axes along which to perform 2D IDWT
149
150
Returns:
151
Reconstructed 2D array
152
"""
153
```
154
155
#### Usage Examples
156
157
```python
158
import pywt
159
import numpy as np
160
import matplotlib.pyplot as plt
161
162
# Create test image with different frequency content
163
x, y = np.mgrid[0:256, 0:256]
164
image = (np.sin(2 * np.pi * x / 64) * np.cos(2 * np.pi * y / 64) + # Low frequency
165
0.5 * np.sin(2 * np.pi * x / 16) * np.cos(2 * np.pi * y / 16) + # Medium frequency
166
0.3 * np.sin(2 * np.pi * x / 4) * np.cos(2 * np.pi * y / 4)) # High frequency
167
168
# Add noise
169
noisy_image = image + 0.2 * np.random.randn(*image.shape)
170
171
# Multi-level 2D decomposition
172
coeffs = pywt.wavedec2(noisy_image, 'db4', level=4)
173
print(f"Number of decomposition levels: {len(coeffs) - 1}")
174
print(f"Approximation shape: {coeffs[0].shape}")
175
for i, (cH, cV, cD) in enumerate(coeffs[1:], 1):
176
print(f"Level {len(coeffs)-i} detail shapes: {cH.shape}, {cV.shape}, {cD.shape}")
177
178
# Perfect reconstruction
179
reconstructed = pywt.waverec2(coeffs, 'db4')
180
print(f"2D Reconstruction error: {np.max(np.abs(noisy_image - reconstructed))}")
181
182
# Image denoising by coefficient thresholding
183
def threshold_coeffs(coeffs, threshold):
184
"""Apply soft thresholding to detail coefficients."""
185
coeffs_thresh = [coeffs[0]] # Keep approximation unchanged
186
for cH, cV, cD in coeffs[1:]:
187
cH_thresh = pywt.threshold(cH, threshold, mode='soft')
188
cV_thresh = pywt.threshold(cV, threshold, mode='soft')
189
cD_thresh = pywt.threshold(cD, threshold, mode='soft')
190
coeffs_thresh.append((cH_thresh, cV_thresh, cD_thresh))
191
return coeffs_thresh
192
193
# Apply thresholding and reconstruct
194
threshold_value = 0.1
195
coeffs_thresh = threshold_coeffs(coeffs, threshold_value)
196
denoised_image = pywt.waverec2(coeffs_thresh, 'db4')
197
198
# Visualization
199
fig, axes = plt.subplots(2, 3, figsize=(15, 10))
200
201
axes[0, 0].imshow(image, cmap='gray')
202
axes[0, 0].set_title('Original Clean Image')
203
axes[0, 0].axis('off')
204
205
axes[0, 1].imshow(noisy_image, cmap='gray')
206
axes[0, 1].set_title('Noisy Image')
207
axes[0, 1].axis('off')
208
209
axes[0, 2].imshow(denoised_image, cmap='gray')
210
axes[0, 2].set_title('Denoised Image')
211
axes[0, 2].axis('off')
212
213
# Show approximation at coarsest level
214
axes[1, 0].imshow(coeffs[0], cmap='gray')
215
axes[1, 0].set_title(f'Approximation Level {len(coeffs)-1}')
216
axes[1, 0].axis('off')
217
218
# Show details at finest level
219
cH1, cV1, cD1 = coeffs[-1]
220
axes[1, 1].imshow(np.abs(cH1), cmap='gray')
221
axes[1, 1].set_title('Horizontal Details (Level 1)')
222
axes[1, 1].axis('off')
223
224
axes[1, 2].imshow(np.abs(cD1), cmap='gray')
225
axes[1, 2].set_title('Diagonal Details (Level 1)')
226
axes[1, 2].axis('off')
227
228
plt.tight_layout()
229
plt.show()
230
231
# Progressive reconstruction - build up from coarse to fine
232
progressive_images = []
233
for level in range(len(coeffs)):
234
# Reconstruct using only levels 0 to level
235
partial_coeffs = coeffs[:level+1]
236
if level < len(coeffs) - 1:
237
# Add zero details for missing levels
238
zero_shape = coeffs[level+1][0].shape
239
for missing_level in range(level+1, len(coeffs)):
240
zero_details = (np.zeros(zero_shape), np.zeros(zero_shape), np.zeros(zero_shape))
241
partial_coeffs.append(zero_details)
242
zero_shape = (zero_shape[0] * 2, zero_shape[1] * 2)
243
244
progressive_image = pywt.waverec2(partial_coeffs, 'db4')
245
progressive_images.append(progressive_image)
246
247
# Show progressive reconstruction
248
fig, axes = plt.subplots(1, len(progressive_images), figsize=(20, 4))
249
for i, (ax, img) in enumerate(zip(axes, progressive_images)):
250
ax.imshow(img, cmap='gray')
251
ax.set_title(f'Up to Level {i}')
252
ax.axis('off')
253
plt.tight_layout()
254
plt.show()
255
```
256
257
### nD Multi-Level DWT
258
259
Hierarchical decomposition and reconstruction for n-dimensional data.
260
261
```python { .api }
262
def wavedecn(data, wavelet, mode: str = 'symmetric', level: int = None, axes=None):
263
"""
264
Multi-level nD discrete wavelet decomposition.
265
266
Parameters:
267
- data: Input nD array
268
- wavelet: Wavelet specification
269
- mode: Signal extension mode for boundary handling
270
- level: Decomposition level (default: maximum possible level)
271
- axes: Axes along which to perform DWT (default: all axes)
272
273
Returns:
274
List [cAn, {details_level_n}, {details_level_n-1}, ..., {details_level_1}] where:
275
- cAn: Approximation coefficients at level n
276
- {details_level_i}: Dictionary of detail coefficients at level i
277
"""
278
279
def waverecn(coeffs, wavelet, mode: str = 'symmetric', axes=None):
280
"""
281
Multi-level nD discrete wavelet reconstruction.
282
283
Parameters:
284
- coeffs: Coefficient list from wavedecn
285
- wavelet: Wavelet specification matching decomposition
286
- mode: Signal extension mode matching decomposition
287
- axes: Axes along which to perform IDWT (should match decomposition)
288
289
Returns:
290
Reconstructed nD array
291
"""
292
```
293
294
#### Usage Examples
295
296
```python
297
import pywt
298
import numpy as np
299
300
# 3D volume example
301
volume = np.random.randn(64, 64, 64)
302
print(f"Original volume shape: {volume.shape}")
303
304
# 3D multi-level decomposition
305
coeffs_3d = pywt.wavedecn(volume, 'db2', level=3)
306
print(f"Number of decomposition levels: {len(coeffs_3d) - 1}")
307
print(f"Approximation shape: {coeffs_3d[0].shape}")
308
309
# Each level has 2^n - 1 detail coefficient arrays (n = number of dimensions)
310
for level, details in enumerate(coeffs_3d[1:], 1):
311
print(f"Level {len(coeffs_3d) - level} details:")
312
for key, coeff in details.items():
313
print(f" '{key}': {coeff.shape}")
314
315
# Perfect reconstruction
316
reconstructed_3d = pywt.waverecn(coeffs_3d, 'db2')
317
print(f"3D reconstruction error: {np.max(np.abs(volume - reconstructed_3d))}")
318
319
# 4D example - 3D spatial + 1D temporal
320
data_4d = np.random.randn(32, 32, 32, 100)
321
coeffs_4d = pywt.wavedecn(data_4d, 'haar', level=2)
322
print(f"4D data shape: {data_4d.shape}")
323
print(f"4D approximation shape: {coeffs_4d[0].shape}")
324
print(f"Number of detail types at each level: {len(coeffs_4d[1])}") # 2^4 - 1 = 15
325
326
# Show some detail coefficient keys for 4D
327
print("4D detail coefficient keys (level 1):")
328
for key in sorted(coeffs_4d[-1].keys()):
329
print(f" '{key}': {coeffs_4d[-1][key].shape}")
330
```
331
332
### Coefficient Utility Functions
333
334
Helper functions for working with multi-level decomposition coefficients and data analysis.
335
336
```python { .api }
337
def downcoef(part: str, data, wavelet, mode: str = 'symmetric', level: int = 1):
338
"""
339
Partial DWT - compute only approximation or detail coefficients.
340
341
Parameters:
342
- part: 'a' for approximation, 'd' for detail coefficients
343
- data: Input signal
344
- wavelet: Wavelet specification
345
- mode: Signal extension mode
346
- level: Decomposition level
347
348
Returns:
349
Requested coefficient type at specified level
350
"""
351
352
def upcoef(part: str, coeffs, wavelet, level: int = 1, take: int = 0):
353
"""
354
Direct reconstruction from single coefficient type.
355
356
Parameters:
357
- part: 'a' for approximation, 'd' for detail coefficients
358
- coeffs: Input coefficients
359
- wavelet: Wavelet specification
360
- level: Number of reconstruction levels
361
- take: Number of coefficients to take (0 = all)
362
363
Returns:
364
Reconstructed signal from specified coefficient type only
365
"""
366
```
367
368
#### Usage Examples
369
370
```python
371
import pywt
372
import numpy as np
373
import matplotlib.pyplot as plt
374
375
# Generate test signal
376
t = np.linspace(0, 1, 1024)
377
signal = np.sin(2 * np.pi * 5 * t) + 0.5 * np.sin(2 * np.pi * 50 * t)
378
379
# Extract only approximation at level 3
380
approx_level3 = pywt.downcoef('a', signal, 'db4', level=3)
381
print(f"Approximation at level 3 shape: {approx_level3.shape}")
382
383
# Extract only detail at level 2
384
detail_level2 = pywt.downcoef('d', signal, 'db4', level=2)
385
print(f"Detail at level 2 shape: {detail_level2.shape}")
386
387
# Reconstruct signal from approximation only
388
reconstructed_approx = pywt.upcoef('a', approx_level3, 'db4', level=3)
389
print(f"Reconstructed from approximation shape: {reconstructed_approx.shape}")
390
391
# Reconstruct signal from detail only
392
reconstructed_detail = pywt.upcoef('d', detail_level2, 'db4', level=2)
393
print(f"Reconstructed from detail shape: {reconstructed_detail.shape}")
394
395
# Visualization
396
plt.figure(figsize=(12, 8))
397
398
plt.subplot(2, 2, 1)
399
plt.plot(t, signal)
400
plt.title('Original Signal')
401
402
plt.subplot(2, 2, 2)
403
plt.plot(reconstructed_approx[:len(signal)])
404
plt.title('Reconstructed from Approximation (Level 3)')
405
406
plt.subplot(2, 2, 3)
407
plt.plot(reconstructed_detail[:len(signal)])
408
plt.title('Reconstructed from Detail (Level 2)')
409
410
plt.subplot(2, 2, 4)
411
plt.plot(t, signal, 'b-', label='Original')
412
plt.plot(reconstructed_approx[:len(signal)] + reconstructed_detail[:len(signal)],
413
'r--', label='Approx + Detail')
414
plt.title('Partial Reconstruction Sum')
415
plt.legend()
416
417
plt.tight_layout()
418
plt.show()
419
420
# Taking partial coefficients
421
partial_approx = pywt.upcoef('a', approx_level3[:len(approx_level3)//2], 'db4', level=3)
422
print(f"Reconstruction from half coefficients: {partial_approx.shape}")
423
```
424
425
### Fully Separable Wavelet Transform
426
427
Advanced transform providing axis-specific decomposition levels for flexible multi-dimensional analysis.
428
429
```python { .api }
430
def fswavedecn(data, wavelet, mode: str = 'symmetric', levels=None, axes=None):
431
"""
432
Fully separable wavelet decomposition.
433
434
Parameters:
435
- data: Input nD array
436
- wavelet: Wavelet specification or list of wavelets for each axis
437
- mode: Signal extension mode or list of modes for each axis
438
- levels: Decomposition levels as int or list of ints for each axis
439
- axes: Axes along which to perform transform (default: all axes)
440
441
Returns:
442
FswavedecnResult object with coefficient access and reconstruction methods
443
"""
444
445
def fswaverecn(fswavedecn_result):
446
"""
447
Inverse fully separable wavelet transform.
448
449
Parameters:
450
- fswavedecn_result: FswavedecnResult object from fswavedecn
451
452
Returns:
453
Reconstructed nD array
454
"""
455
456
class FswavedecnResult:
457
"""Container for fully separable decomposition results."""
458
459
# Properties
460
coeffs: np.ndarray # Coefficient array
461
coeff_slices: list # Coefficient slice information
462
axes: tuple # Transform axes
463
wavelets: list # Wavelets used for each axis
464
modes: list # Extension modes for each axis
465
levels: list # Decomposition levels for each axis
466
approx: np.ndarray # Approximation coefficients
467
468
def __getitem__(self, levels):
469
"""Access coefficients at specified levels."""
470
471
def __setitem__(self, levels, x):
472
"""Set coefficients at specified levels."""
473
474
def detail_keys(self):
475
"""List all detail coefficient keys."""
476
```
477
478
## Types
479
480
```python { .api }
481
# Multi-level coefficient formats
482
MultiLevelCoeffs1D = List[np.ndarray] # [cAn, cDn, cDn-1, ..., cD1]
483
484
MultiLevelCoeffs2D = List[
485
Union[
486
np.ndarray, # Approximation coefficients (first element)
487
Tuple[np.ndarray, np.ndarray, np.ndarray] # (cH, cV, cD) detail tuples
488
]
489
]
490
491
MultiLevelCoeffsND = List[
492
Union[
493
np.ndarray, # Approximation coefficients (first element)
494
Dict[str, np.ndarray] # Detail coefficient dictionaries
495
]
496
]
497
498
# Coefficient part specifications
499
CoeffPart = Literal['a', 'd'] # 'a' for approximation, 'd' for detail
500
```