Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow user to set precision in CWT, increase default to 12 #570

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

OverLordGoldDragon
Copy link

@OverLordGoldDragon OverLordGoldDragon commented Oct 1, 2020

Addresses this Issue. Detailed explanation here; a summary:

  1. Low precision distorts CWT, and heavily at high scales.
  2. With the L2-norm used, scales beyond 64 are increasingly distorted.
  3. Zipper-like artifacts can be seen in computed heatmaps
  4. precision=10 is low, and precision=12 does not add much computation cost, while considerably remedying 1-3.

At the least, the user should get to decide precision instead of carving it in stone. And a doc/comment should be made about these caveats.


Improvement comparison

Code
import numpy as np
import matplotlib.pyplot as plt

from pywt._extensions._pywt import DiscreteContinuousWavelet
from pywt._functions import integrate_wavelet
#%%##########################################################################
def l2(x):
    return np.sqrt(np.sum(np.abs(x ** 2)))

scales = np.power(2 ** (1 / 32), np.arange(1, 320 + 1))
wavelet = DiscreteContinuousWavelet('morl')
#%%##########################################################################
l2res = []
for precision in (10, 12, 14):
    l2res.append([])
    for scale in scales:
        int_psi, x = integrate_wavelet(wavelet, precision=precision)
        step = x[1] - x[0]
        linrange = max(x) - min(x)

        j = np.arange(scale * linrange + 1) / (scale * step)
        j = j.astype(int)  # floor
        if j[-1] >= int_psi.size:
            j = np.extract(j < int_psi.size, j)
        int_psi_scale = int_psi[j][::-1].real
        l2res[-1].append(l2(np.diff(int_psi_scale) * np.sqrt(scale)))
    
#%%##########################################################################
plt.plot(np.log2(scales), l2res[0])
plt.plot(np.log2(scales), l2res[1])
plt.plot(np.log2(scales), l2res[2])
plt.show()

@OverLordGoldDragon OverLordGoldDragon changed the title Allow user to set precision, increase default to 12 Allow user to set precision in CWT, increase default to 12 Oct 1, 2020
Higher `precision` doesn't help with lower scales
pywt/_cwt.py Show resolved Hide resolved
@grlee77
Copy link
Contributor

grlee77 commented Oct 5, 2020

Thanks, I am fine with exposing this parameter.

I will take a look at the info you found soon and review it a little closer.

@OverLordGoldDragon
Copy link
Author

OverLordGoldDragon commented Oct 8, 2020

@grlee77 Some interesting findings here (see bottom); to my surprise, pywt seems to outperform scipy on low scales. Also found a caveat2 (bottom) on integrated wavelet.

I'm curious on rationale behind integrated wavelet, which isn't documented on the site you found; perhaps it can be improved further.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants