Inverting CWT modulus
The problem is known as phase retrieval, and for |CWT|
, the transform is proven invertible to within a global phase shift, $e^{j\omega_0}$, in (1), and an algorithm for recovery is provided in (2):
- Phase recovery for the Cauchy wavelet transform
- Phase retrieval for wavelet transforms -- code
This is excellent invertibility for a wide range of signals. However, it assumes unit stride, or hop_size=1
, or maximum overlap: hop_size > 1
aliases the scalogram and loses information (FR 1). Hopping by half the support of the wavelet is large and will lose a lot.
Answer's algorithm
As written, it's neither DWT nor CWT, but rather CWT with variable stride - which is a valid feature engineering with CWT. With DWT, the answer is simple - recovery from modulus is as good as recovery from |DFT|
, i.e. terrible. With multi-rate CWT, the hop size controls information loss (FR 1). And the Fourier phase, for most purposes, is more important than magnitude, so randomizing phase on per-coefficient basis isn't sound.
But there's other problems. The algorithm has both poor time and poor frequency resolution, per absence of windowing in time domain (or equivalently rectangular windowing). It then inverts with windowing for some reason. Information can also be lost in other ways; there's many ways to do a wavelet transform wrong (FR 2). Pay attention to padding and unpadding; if you're not padding, it's exacerbating the hop problem near edges.
I'm unsure what the algorithm's trying to accomplish, but I suggest first getting comfortable with CWT and its inversion with and without stride. A survey of DWT might also help.
Further reading (FR)
- Role of window length and overlap in uncertainty principle - gives demo of aliasing due to
hop_size
, and provides measure of information loss. hop_size > 1
is OK, but there's also "too much". Note STFT is just non-logscaled CWT (for the described purposes).
- How to validate a wavelet filterbank? - shows nearly all ways in which CWT can go wrong.
- How to test wavelet transforms? - useful test signals. I commented that OP's results are "luck" - that's because even the worst filterbank will work on pure sines of particular frequencies. The TL;DR is to try an exponential chirp with full sweep, or better,
x = echirp(); x += x[::-1]
(see librosa.chirp
or ssqueezepy.TestSignals.echirp
).