PyWavelets / pywt

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

upcoef differs from waverec #698

Open zwiezwerg opened 5 months ago

zwiezwerg commented 5 months ago

I have an issue regarding upcoef and I am not sure whether it is a bug or a misunderstanding on my part. I was trying to reconstruct a signal using upcoef. However, compared to waverec the reconstructions from the individual coefficients using upcoef are shifted versions. Let me illustrate it with an example:

import numpy as np
import pywt
import matplotlib.pyplot as plt
from copy import deepcopy
from pprint import pp

## Signal Def
k = 8
N = 2**k
fs = N
t = np.arange(N)/fs
xlow = 1.5*np.cos(2*np.pi*4*t)
x = xlow

##
wl = pywt.Wavelet('db2')
max_allowed_level = pywt.dwt_max_level(x.shape[0], wl)
coeffs = pywt.wavedec(x, wl, level=max_allowed_level, mode='reflect')

fig, ax = plt.subplots(max_allowed_level+2,1)
reconstruct_upcoef = np.zeros((max_allowed_level + 1, N))
reconstruct_waverec = np.zeros((max_allowed_level + 1, N))
for i in np.arange(max_allowed_level+1):
    reconstruct_upcoef[i, :] = pywt.upcoef('a' if i == 0 else 'd', coeffs[i], wl, level=max_allowed_level - (0 if i < 2 else (i - 1)), take=N)
    coeffs_temp = deepcopy(coeffs)
    for j in np.arange(max_allowed_level+1):
        if i==j:
            continue
        else:
            coeffs_temp[j] = np.zeros_like(coeffs_temp[j])
    reconstruct_waverec[i, :] = pywt.waverec(coeffs_temp, wl, mode='reflect')
    ax[i].plot(reconstruct_upcoef[i, :], label=f'coeff upcoef {i}')
    ax[i].plot(reconstruct_waverec[i, :], label=f'coeff waverec {i}')
ax[max_allowed_level+1].plot(np.sum(reconstruct_upcoef, axis=0), label='x reconstructed upcoef')
ax[max_allowed_level+1].plot(np.sum(reconstruct_waverec, axis=0), label='x reconstructed waverec')
ax[max_allowed_level+1].plot(x, label='x')

pp(f'Reconstruct upcoef: {np.allclose(x, np.sum(reconstruct_upcoef, axis=0))}')
pp(f'Reconstruct waverec: {np.allclose(x, np.sum(reconstruct_waverec, axis=0))}')

##
coeffs_downcoef = []
for i in np.arange(max_allowed_level+1):
    coeffs_downcoef.append(pywt.downcoef('a' if i == 0 else 'd', x, wl, mode='reflect', level=max_allowed_level - (0 if i < 2 else (i - 1))))
pp([np.allclose(c1, c2) for c1, c2, in zip(coeffs, coeffs_downcoef)])

Using the db1 wavelet, the two reconstructions are the same. However, for different wavelets, the offsets are different (even for different levels). As already mentioned, I am not sure, whether this is a bug or if I am understanding the usage of upcoef incorrectly. Note that wavedec and downcoef work the same (see last lines of example).

Thank you very much, BR