PyWavelets / pywt

PyWavelets - Wavelet Transforms in Python
http://pywavelets.readthedocs.org
MIT License
2.04k stars 470 forks source link

swt2 round-trip iswt2 >> swt2 error #560

Closed Noam-M closed 2 years ago

Noam-M commented 4 years ago

Hello,

The round trip swt2 >> iswt2 seems to be working perfectly fine, but the iswt2 >> swt2 does not always result in the same original signal

To show that I start off by generating random coefficients in the transform plane, and then applying iswt2 >> swt2

a = [np.random.random((4, 4)), list(np.random.random((3, 4, 4)))]
b = pywt.iswt2(a, 'haar')
c = pywt.swt2(b, 'haar', level=1, trim_approx=True)
d = pywt.iswt2(c, 'haar')
e = pywt.swt2(d, 'haar', level=1, trim_approx=True)
print(np.allclose(a[0], c[0]))
print(np.allclose(b[0], d[0]))
print(np.allclose(c[0], e[0]))
... 
False
True
True

So we see that the first round trip resulted in an error, while the rest performed as expected. Trying this experiment by generating a random signal, and then applying swt2 >> iswt2 results with all perfect round trips:

a = np.random.random((4, 4))
b = pywt.swt2(a, 'haar', level=1, trim_approx=True)
c = pywt.iswt2(b, 'haar')
d = pywt.swt2(c, 'haar', level=1, trim_approx=True)
e = pywt.iswt2(d, 'haar')
print(np.allclose(a[0], c[0]))
print(np.allclose(b[0], d[0]))
print(np.allclose(c[0], e[0]))
...
True
True
True
grlee77 commented 4 years ago

I don't think you can start with arbitrary signals as the coefficients to iswt2 and expect to get a perfect round-trip when running this type of inverse round trip transform. This is because the wavelet filterbanks are frequency selective (for example the "highpass" or detail filter must actually have amplitude zero at DC). The coefficient arrays from the forward transform have complementary frequency content that enables perfect reconstruction.

consider for example this alternative example of a purposely invalid set of coefficients:

import numpy as np
import pywt
invalid_swt_coeffs = [np.zeros(64), np.ones(64)]  # detail coefficients are at a constant DC offset, which would cannot occur in the forward transform!
b = pywt.iswt(invalid_swt_coeffs, 'haar')
c = pywt.swt(b, 'haar', level=1, trim_approx=True)

Here, the starting coefficients have only a DC component for the highpass which is something that could never occur from the forward transform. Performing a round trip on this from iswt2->swt2 results in coefficients, c which are all zero (to within floating point error).

rgommers commented 2 years ago

The question was answered, and there's nothing to fix. So I'll close this issue.