Skip to content

Commit ed5e03c

Browse files
pavlebgrlee77
authored andcommitted
fix the phase of CWT when using complex mother wavelets (#439)
* When performing CWT the convolution should include complex conjugate of the mother wavelet. For real wavelets this has no influence. * Added comments for the reported bugs in the release notes * TST: take conjugate of precomputed Matlab results from R2012a * fix typo in Matlab reference data generation script * DOC: update release notes add Pavle to the authors.py name map [skip ci] [ci skip] DOC: add link to Lancaster University MODA toolbox [ci skip]
1 parent 399196a commit ed5e03c

File tree

5 files changed

+24
-1
lines changed

5 files changed

+24
-1
lines changed

doc/release/1.1.0-notes.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,25 @@ Deprecated features
1717
Backwards incompatible changes
1818
==============================
1919

20+
When using complex-valued wavelets with the ``cwt``, the output will now be
21+
the complex conjugate of the result that was produced by PyWavelets 1.0.x.
22+
This was done to account for a bug described below. The magnitude of the
23+
``cwt`` coefficients will still match those from previous releases.
24+
2025
Bugs Fixed
2126
==========
2227

28+
For a ``cwt`` with complex wavelets, the results in PyWavelets 1.0.x releases
29+
matched the output of Matlab R2012a's ``cwt``. Howveer, older Matlab releases
30+
like R2012a had a phase that was of opposite sign to that given in textbook
31+
definitions of the CWT (Eq. 2 of Torrence and Compo's review article, "A
32+
Practical Guide to Wavelet Analysis"). Consequently, the wavelet coefficients
33+
were the complex conjugates of the expected result. This was validated by
34+
comparing the results of a transform using ``cmor1.0-1.0`` as compared to the
35+
``cwt`` implementation available in Matlab R2017b as well as the function
36+
``wt.m`` from the Lancaster University Physics department's
37+
`MODA toolbox <https://github.com/luphysics/MODA>`_
38+
2339
Other changes
2440
=============
2541

pywt/_cwt.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ def cwt(data, scales, wavelet, sampling_period=1., method='conv', axis=-1):
124124
out = np.empty((np.size(scales),) + data.shape, dtype=dt_out)
125125
precision = 10
126126
int_psi, x = integrate_wavelet(wavelet, precision=precision)
127+
int_psi = np.conj(int_psi) if wavelet.complex_cwt else int_psi
127128

128129
# convert int_psi, x to the same precision as the data
129130
dt_psi = dt_cplx if int_psi.dtype.kind == 'c' else dt

pywt/tests/data/generate_matlab_data_cwt.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
try:
3838
all_matlab_results = {}
3939
for wavelet in wavelets:
40-
w = pywt.Wavelet(wavelet)
40+
w = pywt.ContinuousWavelet(wavelet)
4141
if np.any((wavelet == np.array(['shan', 'cmor'])),axis=0):
4242
mlab.set_variable('wavelet', wavelet+str(w.bandwidth_frequency)+'-'+str(w.center_frequency))
4343
elif wavelet == 'fbsp':

pywt/tests/test_matlab_compatibility_cwt.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,11 @@ def _check_accuracy(data, w, scales, coefs, wavelet, epsilon):
147147
# PyWavelets result
148148
coefs_pywt, freq = pywt.cwt(data, scales, w)
149149

150+
# coefs from Matlab are from R2012a which is missing the complex conjugate
151+
# as shown in Eq. 2 of Torrence and Compo. We take the complex conjugate of
152+
# the precomputed Matlab result to account for this.
153+
coefs = np.conj(coefs)
154+
150155
# calculate error measures
151156
err = coefs_pywt - coefs
152157
rms = np.real(np.sqrt(np.mean(np.conj(err) * err)))

util/authors.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
u('Helder'): u('Helder Oliveira'),
3131
u('Kai'): u('Kai Wohlfahrt'),
3232
u('asnt'): u('Alexandre Saint'),
33+
u('pavleb'): u('Pavle Boškoski'),
3334
}
3435

3536

0 commit comments

Comments
 (0)