PyWavelets / pywt

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

Multilevel reconstruction with omitted coefficients #336

Closed ulaai closed 7 years ago

ulaai commented 7 years ago

I'm trying to denoise an ECG signal. I want to omit the approximation and level 1 & 2 details from the signal, then reconstruct it. I looked around and followed #302. This is what I currently have:

ds = np.array(d_signal)

#coeffs = [cA_n, cD_n, cD_n-1, ..., cD2, cD1]
coeffs = pywt.wavedecn(d_signal, 'db6', level=9)

coeffs[0] = {k: None for k, v in coeffs[0].items()}
coeffs[9] = {k: None for k, v in coeffs[9].items()}
coeffs[8] = {k: None for k, v in coeffs[8].items()}

#reconstruct from 3rd to 9
ds = pywt.waverecn(coeffs, 'db6')

plt.plot(ds)
plt.show()

I read that there is implementation already in #303 but I can't seem to wrap my head around this. I got the error:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-75-44ffb5678222> in <module>()
      4 coeffs = pywt.wavedecn(ds, 'db6', level=9)
      5 
----> 6 coeffs[0] = {k: None for k, v in coeffs[0].items()}
      7 coeffs[9] = {k: None for k, v in coeffs[9].items()}
      8 coeffs[8] = {k: None for k, v in coeffs[8].items()}

AttributeError: 'numpy.ndarray' object has no attribute 'items'

I also tried using other alternative solutions (from the same #302), like setting the coefficients to None but it also raised an error.

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-76-a60cf4784a40> in <module>()
      9 
     10 #reconstruct from 3rd to 9
---> 11 ds = pywt.waverecn(coeffs, 'db6')
     12 
     13 plt.plot(ds)

~\Anaconda2\envs\py36\lib\site-packages\pywt\_multilevel.py in waverecn(coeffs, wavelet, mode, axes)
    460 
    461     # Raise error for invalid key combinations
--> 462     ds = list(map(_fix_coeffs, ds))
    463 
    464     if not ds:

~\Anaconda2\envs\py36\lib\site-packages\pywt\_multidim.py in _fix_coeffs(coeffs)
    184 
    185 def _fix_coeffs(coeffs):
--> 186     missing_keys = [k for k, v in coeffs.items() if
    187                     v is None]
    188     if missing_keys:

AttributeError: 'NoneType' object has no attribute 'items'

Please let me know if I'm doing this wrong, I'm new to wavelets and this library. Thank you very much.

grlee77 commented 7 years ago

The message AttributeError: 'numpy.ndarray' object has no attribute 'items' is because coeffs[0] is an array, not a dictionary, so you cannot use .items() on it. The first element of coeffs is an array containing the approximation coefficients. The remaining elements of the list are dictionaries containing the various detail coefficients at each level of decomposition (see the wavedecn documentation for more details of the output format).

If you want the approximation coefficients set to zero you can do either:

coeffs[0] = np.zeros_like(coeffs[0])

or

coeffs[0][:] = 0

For the remaining levels, you can replace the coefficients with arrays of zeros using a statement of the form suggested in #303:

coeffs[1] = {k: np.zeros_like(v) for k, v in coeffs[1].items()}
ulaai commented 7 years ago

Thank you for your help!

grlee77 commented 7 years ago

You might also want to check out denoise_wavelet from scikit-image (it is implemented using PyWavelets). Despite being in an "image processing" library, it should also work for 1D ECG data. The coefficient thresholding used there is likely going to work better than just setting all coefficients at a given level to zero.