Master the Discrete wavelet reconstruction methods using easily understanding examples
The methods for 1D Single-Level Discrete Wavelet Transform in Python will be discussed in the following 3 parts:
(II): Wavelet Reconstruction
In the last part (I), we have talked about how to decompose a 1D signal into approximation and detail coefficients at the first level. The next part of the story of Discrete wavelet transform is how to reconstruct the signal from these decomposition components. In this post, we discuss this top still using simple examples so that you can easily grasp the method.
1. Inverse Discrete Wavelet Transform (idwt)
We perform single levelidwt
(inverse Discrete Wavelet Transform) method to reconstructs a signal from the first-level decomposition coefficients.
pywt.idwt(cA, cD, wavelet, mode='sym', correct_size=0)
Parameters:
- cA: Approximation coefficient.
- cD: Detail coefficient.
- wavelet: Wavelet used in the transform
- mode: Signal extension mode to deal with the border distortion problem
- correct_size: Typically, cA and cD coefficients must have same lengths in order to perform IDWT. Setting correct_size to True allows cA to be greater in size by one element than the cD size.
Return:
- the reconstructed signal
2. Example 1: Even Length Signal
First, let’s create a simple signal with values from 1 to 100. First, let’s decompose it using the dwt
method learned in the last part.
(1) Create a signal
s_even = list(range(1,101)) print(s_even)
The result is:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]
(2) Decompose it at the first level
We use sym3
discrete wavelet and constant
extension mode.
import pywt (cA,cD) = pywt.dwt(s_even,'sym3','constant') # Symlets 3 (sym3) print('Approximation Coefficient: \n',cA) print('Detail Coefficient: \n',cD)
Approximation Coefficient: [ 1.44943985 1.21399887 2.57019338 5.3986205 8.22704763 11.05547475 13.88390188 16.712329 19.54075613 22.36918325 25.19761038 28.0260375 30.85446463 33.68289175 36.51131888 39.339746 42.16817313 44.99660025 47.82502738 50.6534545 53.48188163 56.31030875 59.13873587 61.967163 64.79559012 67.62401725 70.45244437 73.2808715 76.10929862 78.93772575 81.76615287 84.59458 87.42300712 90.25143425 93.07986137 95.9082885 98.73671562 101.56514275 104.39356987 107.221997 110.05042412 112.87885124 115.70727837 118.53570549 121.36413262 124.19255974 127.02098687 129.84941399 132.67784112 135.50626824 138.34968406 141.08868568] Detail Coefficient: [-3.32670553e-01 1.55893858e-01 -9.61654367e-13 -6.95765667e-12 -1.29543598e-11 -1.89513127e-11 -2.49475995e-11 -3.09423043e-11 -3.69395625e-11 -4.29357661e-11 -4.89323027e-11 -5.49287282e-11 -6.09251538e-11 -6.69194700e-11 -7.29143412e-11 -7.89122101e-11 -8.49103010e-11 -9.09072817e-11 -9.69069269e-11 -1.02899467e-10 -1.08896225e-10 -1.14888765e-10 -1.20889299e-10 -1.26885169e-10 -1.32881262e-10 -1.38878242e-10 -1.44877665e-10 -1.50867097e-10 -1.56860080e-10 -1.62855951e-10 -1.68856928e-10 -1.74852577e-10 -1.80850002e-10 -1.86848315e-10 -1.92848848e-10 -1.98839167e-10 -2.04833928e-10 -2.10831352e-10 -2.16827889e-10 -2.22815544e-10 -2.28834729e-10 -2.34824160e-10 -2.40813591e-10 -2.46802134e-10 -2.52798671e-10 -2.58802313e-10 -2.64790856e-10 -2.70794942e-10 -2.76785261e-10 -2.82780022e-10 -1.41550404e-01 -3.52262922e-02]
(3) Reconstruct the signal
Now, let’s reconstruct the signal using idwt
method. The same wavelet and extension should be used in the wavelet decomposition and reconstruction.
s_even_recon = pywt.idwt(cA, cD, 'sym3', 'constant') print(s_even_recon)
[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100.]
The reconstruction result reveals that it successfully reconstruct the signal.
However, it is not so easy to see the result for a complicate real-world signal. Then we have to evaluate the method through comparison tests, such as length and errors.
(i) check the length
print('Length of the orignal signal:',len(s_even)) print('Length of the reconstructed signal:',len(s_even_recon))
Length of the orignal signal: 100 Length of the reconstructed signal: 100
So the length of the reconstructed signal has the same length with the original.
(ii) check the errors
Here, let’s evaluate the reconstruction using Mean absolute error (MAE) and maximum absolute error(Max. AE).
print('MAE:', sum(abs(s_even-s_even_recon))/len(S)) print('Max.AE:',max(abs(s_even-s_even_recon)))
MAE: 5.769074107320193e-13 Max.AE: 1.0771827874123119e-11
From the above results, we can see that there are very small errors, which can be ignored. This is why we see the reconstructed signal is just the same with the original, except that values are expressed by float.
The question next is how about the signal of odd length? Let’s discuss it as follows.
3. Example 2: Odd Length Signal
(1) Create the signal
Suppose our signal is odd length with values ranging from 1 to 99, for example.
s_odd = list(range(1,100)) print(s_odd)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
(2) Decompose the signal
Let’s decompose it first. We use cA1
and cD1
this time in order for comparison with the even signal.
(cA1,cD1) = pywt.dwt(s_odd,'sym3','constant') # Symlets 3 (sym3) print('Approximation Coefficient: \n',cA1) print('Detail Coefficient: \n',cD1)
Approximation Coefficient: [ 1.44943985 1.21399887 2.57019338 5.3986205 8.22704763 11.05547475 13.88390188 16.712329 19.54075613 22.36918325 25.19761038 28.0260375 30.85446463 33.68289175 36.51131888 39.339746 42.16817313 44.99660025 47.82502738 50.6534545 53.48188163 56.31030875 59.13873587 61.967163 64.79559012 67.62401725 70.45244437 73.2808715 76.10929862 78.93772575 81.76615287 84.59458 87.42300712 90.25143425 93.07986137 95.9082885 98.73671562 101.56514275 104.39356987 107.221997 110.05042412 112.87885124 115.70727837 118.53570549 121.36413262 124.19255974 127.02098687 129.84941399 132.67784112 135.47104195 138.53491006 140.00714267] Detail Coefficient: [-3.32670553e-01 1.55893858e-01 -9.61654367e-13 -6.95765667e-12 -1.29543598e-11 -1.89513127e-11 -2.49475995e-11 -3.09423043e-11 -3.69395625e-11 -4.29357661e-11 -4.89323027e-11 -5.49287282e-11 -6.09251538e-11 -6.69194700e-11 -7.29143412e-11 -7.89122101e-11 -8.49103010e-11 -9.09072817e-11 -9.69069269e-11 -1.02899467e-10 -1.08896225e-10 -1.14888765e-10 -1.20889299e-10 -1.26885169e-10 -1.32881262e-10 -1.38878242e-10 -1.44877665e-10 -1.50867097e-10 -1.56860080e-10 -1.62855951e-10 -1.68856928e-10 -1.74852577e-10 -1.80850002e-10 -1.86848315e-10 -1.92848848e-10 -1.98839167e-10 -2.04833928e-10 -2.10831352e-10 -2.16827889e-10 -2.22815544e-10 -2.28834729e-10 -2.34824160e-10 -2.40813591e-10 -2.46802134e-10 -2.52798671e-10 -2.58802313e-10 -2.64790856e-10 -2.70794942e-10 -2.76785261e-10 3.32670553e-01 -1.55893858e-01 -2.96810576e-10]
(3) Reconstruct the signal
s_odd_recon = pywt.idwt(cA1, cD1, 'sym3', 'constant') print(s_odd_recon)
[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 99.]
(4) Evaluate the results
# check length print('Length of the orignal signal:',len(s_odd)) print('Length of the reconstructed signal:',len(s_odd_recon))
Length of the orignal signal: 99 Length of the reconstructed signal: 100
We can see that the original signal has 99 values, while the reconstructed signal has 100 values. If we check the reconstructed signal, we found that there is another ‘99’ was added. It will add one more value at end based on the extension model because DWT requires even number length of the signal.
Thus, the reconstructed signal should be the one after removing the extra value.
# reconstructed signal s_odd_recon = s_odd_recon[:-1] print(s_odd_recon)
[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99.]
So we cannot see any different between the reconstructed signal and the original one from the above result. Whereas, they are the same because there might be errors, since the signal is transformed through filters, downsampling and upsampling. Let’s check to confirm the conclusion.
print('MAE:', sum(abs(s_odd-s_odd_recon))/len(S)) print('Max.AE:',max(abs(s_odd-s_odd_recon)))
MAE: 5.766231936377153e-13 Max.AE: 1.0786038728838321e-11