0
$\begingroup$

I'm looking for a way to partially reconstruct branches of a wavelet decomposition, such that the sum would recreate the original signal. This could be achieved in MATLAB using:

DATA = [0,1,2,3,4,5,6,7,8,9]
N_LEVELS = 2;
WAVELET_NAME = 'db4';
[C,L] = wavedec(DATA, N_LEVELS, WAVELET_NAME);
A2 = wrcoef('a', C, L, WAVELET_NAME, 2);
D2 = wrcoef('d', C, L, WAVELET_NAME, 2);
D1 = wrcoef('d', C, L, WAVELET_NAME, 1);
A2+D2+D1

ans =

    0.0000    1.0000    2.0000    3.0000    4.0000    5.0000    6.0000    7.0000    8.0000    9.0000

I'd like to achieve the same using pywt, but I'm not sure how to go about this. The pywt.waverec function creates a full reconstruction, but doesn't have a level parameter for partial reconstruction. The pywt.upcoef function does what I need for a single level but I'm not sure how to expand this for multiple levels:

>>> import pywt
>>> data = [1,2,3,4,5,6]
>>> (cA, cD) = pywt.dwt(data, 'db2', 'smooth')
>>> n = len(data)
>>> pywt.upcoef('a', cA, 'db2', take=n) + pywt.upcoef('d', cD, 'db2', take=n)
array([ 1.,  2.,  3.,  4.,  5.,  6.])
$\endgroup$
0
$\begingroup$

I managed to write my own version of the wrcoef function which appears to work as expected:

import pywt
import pdb
import numpy as np

def wrcoef(X, coef_type, coeffs, wavename, level):
    N = np.array(X).size
    a, ds = coeffs[0], list(reversed(coeffs[1:]))

    if coef_type =='a':
        return pywt.upcoef('a', a, wavename, level=level)[:N]
    elif coef_type == 'd':
        return pywt.upcoef('d', ds[level-1], wavename, level=level)[:N]
    else:
        raise ValueError("Invalid coefficient type: {}".format(coef_type))



level = 4
X = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]
coeffs = pywt.wavedec(X, 'db1', level=level)
A4 = wrcoef(X, 'a', coeffs, 'db1', level)
D4 = wrcoef(X, 'd', coeffs, 'db1', level)
D3 = wrcoef(X, 'd', coeffs, 'db1', 3)
D2 = wrcoef(X, 'd', coeffs, 'db1', 2)
D1 = wrcoef(X, 'd', coeffs, 'db1', 1)
print A4 + D4 + D3 + D2 + D1

# Results:
[  9.99200722e-16   1.00000000e+00   2.00000000e+00   3.00000000e+00
   4.00000000e+00   5.00000000e+00   6.00000000e+00   7.00000000e+00
   8.00000000e+00   9.00000000e+00   1.00000000e+01   1.10000000e+01
   1.20000000e+01   1.30000000e+01   1.40000000e+01   1.50000000e+01
   1.60000000e+01   1.70000000e+01]
$\endgroup$
0
$\begingroup$

Well, there is no one size fits all solution for your question, because the function wrcoef is not implemented by authors of PyWavelets module, and, in general, there is no closed-form solution expreced in terms of other functions of the module, such as upcoef / downcoef. You should implement the logic behind Matlab's wrcoef function by yourself, and that logic is slightly different for wavelets families. A month ago I've implemented it for Symlets: the Python implementation is totally based on Matlab's codes. If it would be interesting for you, I can post the solution here.

Sam's solution works as expected only for the Haar wavelet (i.e. Db1). For example, for the initial question the following code in Python:

import pywt
import numpy as np

DATA = range(10)
N_LEVELS = 2
WAVELET_NAME = 'db4'
coeffs = pywt.wavedec(DATA, WAVELET_NAME, level=N_LEVELS)
A2 = wrcoef(DATA, 'a', coeffs, WAVELET_NAME, N_LEVELS)
D2 = wrcoef(DATA, 'd', coeffs, WAVELET_NAME, N_LEVELS)
D1 = wrcoef(DATA, 'd', coeffs, WAVELET_NAME, 1)
print(np.max(np.abs(DATA - (A2 + D2 + D1))))

returns 17.0266582097. Moreover, comparing the values of A2, D2 and D1 to the output of the corresponding functions in Matlab, it seems that the proposed function does not returned the expected values.

PS Due to the small input size, in order to run the code above you should rewrite the function pywt.wavedec in such a way that there is no check of the input level or, instead of that, you can just comment the following line

# level = _check_level(axes_shape, wavelet.dec_len, level)

in the script _multilevel.py.

$\endgroup$
  • $\begingroup$ Thanks for pointing this out. At the time I just needed a quick solution that worked for Db1, but for future work if you could post your solution that could be really helpful. $\endgroup$ – Sam Perry Oct 29 '17 at 12:43
  • $\begingroup$ @Sam Perry, Sam, I've just submitted the code to github, see the function wrcoef. $\endgroup$ – Ilya Jan 14 '18 at 3:01
0
$\begingroup$

Currently, pywt has not implemented wrcoef equivalent function yet. But you still can decompose 1-D multilevel signal then reconstruct its components separately.

https://stackoverflow.com/a/47591523/2845274

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.