Giter Site home page Giter Site logo

ucd4ids / continuouswavelets.jl Goto Github PK

View Code? Open in Web Editor NEW
20.0 1.0 7.0 5.99 MB

wide array of continuous wavelet transforms using Julia

Home Page: https://dsweber2.github.io/ContinuousWavelets.jl/dev/

License: Other

Julia 99.61% Python 0.39%
wavelets julia signal-processing

continuouswavelets.jl's Introduction

ContinuousWavelets

Build Status Coverage

This package is an offshoot of Wavelets.jl for the continuous wavelets. Thanks to Felix Gerick for the initial implementation there, with extension and further adaptation by David Weber and any other contributors listed on the right. Currently, it implements 1D continuous wavelet transforms with the following mother wavelets:

Mothers

Which covers several standard continuous wavelet families, both real and analytic, as well as continuous versions of the orthogonal wavelet transforms implemented in Wavelets.jl.

Basic Usage

Install via the package manager and load with using

julia> Pkg.add("ContinuousWavelets")
julia> using ContinuousWavelets

Basic usage example on a doppler test function.

julia> using ContinuousWavelets, Plots, Wavelets

julia> n = 2047;

julia> t = range(0, n / 1000, length=n); # 1kHz sampling rate

julia> f = testfunction(n, "Doppler");

julia> p1 = plot(t, f, legend=false, title="Doppler", xticks=false)
Plot{Plots.PyPlotBackend() n=1}

julia> c = wavelet(Morlet(π), β=2)
CWT{Morlet mean 3.141592653589793, Father Wavelet, Q=8.0, β=2.0,aveLen=0.0, frame=1.0, norm=Inf, extraOctaves=0.0}

julia> res = cwt(f, c)
┌ Warning: the lowest frequency wavelet has more than 1% its max at zero, so it may not be analytic. Think carefully
│   lowAprxAnalyt = 0.061863
└ @ ContinuousWavelets ~/work/ContinuousWavelets.jl/ContinuousWavelets.jl/src/sanityChecks.jl:7
2047×31 Matrix{ComplexF64}:
 -1.48637e-6+3.8241e-19im     0.000109978+9.67834e-5im
 -1.48602e-6+5.15534e-19im     -8.24922e-5+0.000130656im
                                        
 0.000435175+2.30636e-19im    -2.47195e-6-1.97048e-8im
 0.000435027-8.28725e-19im     -2.63499e-6+4.62331e-8im

And now we make a scalogram to actually visualize these entries:

freqs = getMeanFreq(computeWavelets(n, c)[1])
freqs[1] = 0
p2 = heatmap(t, freqs, log.(abs.(res).^2)', xlabel= "time (s)", ylabel="frequency (Hz)", colorbar=false, c=cgrad(:viridis, scale=:log10))
l = @layout [a{.3h};b{.7h}]
plot(p1,p2,layout=l)

Doppler

As the cwt frame is redundant, there are many choices of dual/inverse frames. There are three available in this package, NaiveDelta(), PenroseDelta(), and DualFrames(). As a toy example, lets knock out the middle time of the bumps function and apply a high pass filter:

f = testfunction(n, "Bumps");
p1 = plot(f, legend = false, title = "Bumps", xlims = (0, 2000), linewidth = 2)
c = wavelet(dog2, β = 2)
res = cwt(f, c);
# dropping the middle peaks
res[620:1100, :] .= 0
# and smoothing the remaining peaks
res[:, 10:end] .= 0
freqs = getMeanFreq(length(f), c)
p2 = heatmap(1:n, freqs, abs.(res)', xlabel = "time (ms)", ylabel = "Frequency (Hz)", colorbar = false, c = :viridis)
dropped = icwt(res, c, DualFrames());
p1 = plot(f, legend=false, title="Smoothing and dropping bumps", linewidth=2)
plot!(dropped, linewidth=3)
l = @layout [a{0.3h}; b{0.7h}]
plot(p1, p2, layout=l)

Bumps

It can also handle collections of examples at the same time, should you need to do a batch of transforms:

julia> exs = cat(testfunction(n, "Doppler"), testfunction(n, "Blocks"), testfunction(n, "Bumps"), testfunction(n, "HeaviSine"), dims=2);

julia> c = wavelet(cDb2, β=2, extraOctaves=-0)
CWT{Continuous db2, Father Wavelet, Q=8.0, β=2.0,aveLen=0.0, frame=1.0, norm=Inf, extraOctaves=0.0}

julia> res = circshift(cwt(exs, c), (0, 1, 0))
┌ Warning: the highest frequency wavelet has more than 1% its max at the end, so it may not be analytic. Think carefully
│   highAprxAnalyt = 0.2677814440444114
└ @ ContinuousWavelets ~/work/ContinuousWavelets.jl/ContinuousWavelets.jl/src/sanityChecks.jl:10
2047×32×4 Array{Float64, 3}:
[:, :, 1] =
 1.89367e-5  0.000266033    4.6727e-5    2.99983e-6
 8.33321e-5  0.000266913     1.56557e-5  -4.46419e-5
                           
 2.24677e-6  0.00198709     4.24042e-6   3.80685e-6
 2.63848e-6  0.00198004      4.3791e-6    3.47575e-6

[:, :, 2] =
  7.81007e-18  0.0226754  0.00955729     3.68809e-18
 -3.47114e-18  0.022684   0.00950443     -3.47114e-18
                                     
 -9.29595e-18  0.0341512  0.0108039     -3.84208e-19
  1.27592e-18  0.0342157  0.0107729      -1.7043e-18

[:, :, 3] =
 -4.2736e-7   0.0059687     4.47839e-8  1.86209e-8
 -4.39691e-7  0.00596762     3.30771e-8  7.78201e-9
                           
 -9.41123e-8  0.00339924    8.01012e-9  4.78652e-9
 -9.36079e-8  0.0034061      8.3188e-9   4.24252e-9

[:, :, 4] =
  0.000307454  -0.0150898   -0.00391724     0.000301757
  6.05948e-5   -0.0152536   -0.00405883      8.45503e-5
                                        
 -0.000307094  -0.00755439  -0.00156729    -0.000594673
 -0.000378125  -0.00746687  -0.00146262     -0.00051676

And the plot of these:

p1 = plot(plot(exs[:, 1], legend=false, title="Doppler", yticks=[], xticks=[], linewidth=2), plot(exs[:, 2], legend=false, title="Blocks", yticks=[], xticks=[], linewidth=2), plot(exs[:, 3], legend=false, title="Bumps", yticks=[], xticks=[], linewidth=2), plot(exs[:, 4], legend=false, title="HeaviSine", yticks=[], xticks=[], linewidth=2), layout=(1, 4))
p2 = plot(heatmap(identity.(res[:, :, 1])', xticks=false, yticks=[], c=:viridis, colorbar=false), heatmap(identity.(res[:, :, 2])', xticks=false, yticks=[], c=:viridis, colorbar=false), heatmap(identity.(res[:, :, 3])', xticks=false, yticks=[], c=:viridis, colorbar=false), heatmap(identity.(res[:, :, 4])', xticks=false, yticks=[], c=:viridis, colorbar=false), layout=(1, 4))
l = @layout [a{0.3h}; b{0.7h}]
plot(p1, p2, layout=l)

parallel transforms

There are also several boundary conditions, depending on the kind of data given; the default SymBoundary() symmetrizes the data, while PerBoundary() assumes it is periodic, and ZPBoundary pads with zeros. All wavelets are stored in the Fourier domain, and all transforms consist of performing an fft (possibly an rfft if the data is real) of the input, pointwise multiplication (equivalent to convolution in the time domain), and then returning to the time domain.

Perhaps somewhat unusually, the averaging function, or father wavelet, is included as an option (the bottom row for the figure above). This can be either the paired averaging function or uniform in frequency (the Dirac averaging). The frequency coverage of the wavelets can be adjusted both in total frequency range both below by the averagingLength or above by the extraOctaves (caveat emptor with how well they will be defined in that case). The frequency density can be adjusted both in terms of the quality/scale factor Q, as well as how quickly this density falls off as the frequency goes to zero via β. Finally, depending on what kind of norm you want to preserve, p determines the norm preserved in the frequency domain (so p=1 maintains the 1-norm in frequency, while p=Inf maintains the 1-norm in time).

Possible extensions

  • Higher dimensional wavelets have yet to be implemented.
  • A DCT implementation of the symmetric boundary to halve the space and computational costs.

continuouswavelets.jl's People

Contributors

dsweber2 avatar github-actions[bot] avatar henry2004y avatar mapi1 avatar wchak avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

continuouswavelets.jl's Issues

Error in README demo

The first example in README returns error because

julia> freqs = getMeanFreq(computeWavelets(n, c)[1])
WARNING: both ContinuousWavelets and Wavelets export "computeWavelets"; uses of it in module Main must be qualified
ERROR: UndefVarError: computeWavelets not defined

I guess this indicates that this package is still during the transition phase? One quick fix would be

freqs = getMeanFreq(ContinuousWavelets.computeWavelets(n, c)[1])

Docs and examples for Morse Wavelets

We should probably document the features and some examples of the Morse wavelets at some point, both by changing the Mothers.svg file (generated in the this file). And in the actual docs

Spelling error on mothers.svg

There is a spelling error in one of the wavelet plots in docs/mothers.svg.
The mother wavelet function at the upper right is spelled as "Beylkyin". But the correct spelling is "Beylkin".
Please fix this minor typo.

Unused argument

Is the argument nSpace supposed to be used here? I'm having a hard time figuring out what computeWavelets and computeOmega does, as I thought omega meant the frequency(0~Nyquist) but it doesn't seem like computeOmega outputs that.

Duplicate `morsefreq`

There are two versions of the morsefreq method, one in src/utils.jl and the other in src/createWavelets.jl. These two are identical in arguments, and the current include ordering in src/ContinuousWavelets.jl makes the latter the one actually being used.

However, there is one tiny difference between the two versions. The one in utils has one extra line which divides the frequency by 2pi, which I guess converts the output into angular frequency

fm = fm / (2 * pi);

Fix Docs build

ongoing problem where floating point can cause headaches for doctests, especially complex floating point

Error calling `range` when running basic example from readme

Running the basic example from the readme file:

    function CWT_example()
            n = 2047;
            t = range(0, n/1000, length = n); # 1kHz sampling rate
            f = testfunction(n, "Doppler");
            p1 = plot(t, f, legend = false, title="Doppler", xticks=false)
            c = wavelet(Morlet(π), β = 2);
            res = ContinuousWavelets.cwt(f, c)
            freqs = getMeanFreq(ContinuousWavelets.computeWavelets(n, c)[1])
            freqs[1] = 0
            p2 = heatmap(t,freqs, abs.(res)', xlabel= "time (s)", ylabel="frequency (Hz)",colorbar=false)
            l = @layout [a{.3h};b{.7h}]
            plot(p1,p2,layout=l)
    end

gives the following error:

  ┌ Warning: the lowest frequency wavelet has more than 1% its max at zero, so it may not be analytic. Think carefully
  │   lowAprxAnalyt = 0.06186323501016359
  └ @ ContinuousWavelets ~/.julia/packages/ContinuousWavelets/rDi28/src/sanityChecks.jl:6
  ┌ Warning: the lowest frequency wavelet has more than 1% its max at zero, so it may not be analytic. Think carefully
  │   lowAprxAnalyt = 0.06186323501016359
  └ @ ContinuousWavelets ~/.julia/packages/ContinuousWavelets/rDi28/src/sanityChecks.jl:6
  ERROR: LoadError: ArgumentError: range(0.0, stop=1000.0, length=1): endpoints differ
  Stacktrace:
    [1] _linspace1(#unused#::Type{Float64}, start::Float64, stop::Float64, len::Int64)
      @ Base ./twiceprecision.jl:678
    [2] _range(start::Float64, #unused#::Nothing, stop::Float64, len::Int64)
      @ Base ./twiceprecision.jl:595
    [3] _range
      @ ./range.jl:437 [inlined]
    [4] _range2
      @ ./range.jl:100 [inlined]
    [5] #range#58
      @ ./range.jl:94 [inlined]
    [6] getMeanFreq(Ŵ::Matrix{Float64}, fsample::Int64)
      @ ContinuousWavelets ~/.julia/packages/ContinuousWavelets/rDi28/src/utils.jl:248
    [7] getMeanFreq(Ŵ::Matrix{Float64})
      @ ContinuousWavelets ~/.julia/packages/ContinuousWavelets/rDi28/src/utils.jl:247
    [8] CWT_example()

TagBot trigger issue

This issue is used to trigger TagBot; feel free to unsubscribe.

If you haven't already, you should update your TagBot.yml to include issue comment triggers.
Please see this post on Discourse for instructions and more details.

If you'd like for me to do this for you, comment TagBot fix on this issue.
I'll open a PR within a few hours, please be patient!

[Bug?] getMeanFreq gives non-monotonous values for some wavelets

Hi,
I've noticed some unexpected behaviour of the function getMeanFreq, which returns non-monotonous values for some wavelets. I stumbled upon this issue when playing around with the example code of the readme; for some wavelets, the heatmap would not be plotted because it requires increasing y-values, which are given by getMeanFreq in the example code.
Disclaimer: I have very little knowledge of wavelets and how they function. Perhaps this behaviour is expected or even intended; it does strike me as quite odd, though.
I have not done a thorough test but tried only a few cases. My observations are as such:

  • no issues for Morlet, no matter what parameters I gave it
  • Battle-Lemarie 4 is problematic for β=1 and large signals but fine for short-ish ones (<10000)
  • Haar is problematic even for comparable short signals (~1000)

MWE:

using ContinuousWavelets, Plots
x = 100000 # cBatt4 is fine for x<10000 but cHaar has issues even for ~1000
c1 = wavelet(Morlet(), β=1)
f1 = getMeanFreq(computeWavelets(x, c1)[1])
c2 = wavelet(cBatt4, β=1) # no problem for β=2, but β=1 causes issues for large x
f2 = getMeanFreq(computeWavelets(x, c2)[1])
c3 = wavelet(cHaar)
f3 = getMeanFreq(computeWavelets(x, c3)[1])
plot(f1, yscale=:log10, label="Morlet()", xlabel="i", ylabel="νᵢ", key=:bottomright)
plot!(f2, label="cBatt4")
plot!(f3, label="cHaar")

The resulting plot:
wavelets_error

Should this behaviour be intended, please feel free to discard this report. Many thanks for providing this package!

Function name clash

Hi, it looks like Wavelets has implemented undocumented cwt and computeWavelets so the example needs to qualify those functions. It is great to have this package available - thanks!

Simple access to a wavelet ?

Hi, is there any simple way to directly access any wavelet as a function ?
For example,

m = Morlet()
m(0.5) # should output the value of the Morlet wavelet at the point 0.5.

Thanks !
Simon

Discrepancy between CWT in ContinuousWavelets, Matlab and R

Hi,

I ran a CWT using ContinuousWavelets, Matlab WTC package (Grinstead), and R's Biwavelet package, on the same signal.
The result are consistent between R and matlab, but not at all with ContinuousWavelets. Can you help me?

signal = Matrix{Float64}(DataFrame(CSV.File("data.csv")))

       signal = Matrix{Float64}(DataFrame(CSV.File("data.csv")))

signal = vec(signal)



        c = ContinuousWavelets.CWT(Morlet());

        res = ContinuousWavelets.cwt(signal, c)

        Plots.heatmap(abs.(res)', xlabel= "time index",
        ylabel="frequency index",colorbar=false)

data.csv
Screenshot from 2024-06-14 12-25-12

Documenter error for test under Julia v1.9.0

I upgraded Julia from v1.8.5 to v1.9 yesterday. And I just ran test of ContinuousWavelets.jl and got the error related to Documenter as follows. If you could check what needs to be changed and fix this, I highly appreciate it.

Precompiling project...
  3 dependencies successfully precompiled in 4 seconds. 45 already precompiled.
     Testing Running tests...
┌ Warning: Unable to determine HTML(edit_link = ...) from remote HEAD branch, defaulting to "master".
│ Calling `git remote` failed with an exception. Set JULIA_DEBUG=Documenter to see the error.
│ Unless this is due to a configuration error, the relevant variable should be set explicitly.
└ @ Documenter.Utilities ~/.julia/packages/Documenter/H5y27/src/Utilities/Utilities.jl:822
[ Info: SetupBuildDirectory: setting up build directory.
[ Info: Doctest: running doctests.
CWT{Morlet mean 3.141592653589793, Father Wavelet, Q=8.0, β=2.0,aveLen=0.0, frame=1.0, norm=Inf, extraOctaves=0.0}┌ Error: doctest failure in ~/.julia/packages/ContinuousWavelets/arobh/docs/src/README.md:30-56
│ 
│ ```jldoctest ex
│ julia> using Random
│ 
│ julia> Random.seed!(1234);
│ 
│ julia> using ContinuousWavelets, Wavelets
│ 
│ julia> n = 2047;
│ 
│ julia> t = range(0, n / 1000, length=n); # 1kHz sampling rate
│ 
│ julia> f = testfunction(n, "Doppler");
│ 
│ julia> c = wavelet(Morlet(π), β=2)
│ 
│ julia> res = ContinuousWavelets.cwt(f, c)
│ ┌ Warning: the lowest frequency wavelet has more than 1% its max at zero, so it may not be analytic. Think carefully
│ │   lowAprxAnalyt = 0.061863
│ └ @ ContinuousWavelets ~/work/ContinuousWavelets.jl/ContinuousWavelets.jl/src/sanityChecks.jl:6
│ 2047×31 Matrix{ComplexF64}:
│  -1.48637e-6+3.8241e-19im   …  0.000109978+9.67834e-5im
│  -1.48602e-6+5.15534e-19im     -8.24922e-5+0.000130656im
│             ⋮               ⋱             ⋮
│  0.000435175+2.30636e-19im  …  -2.47195e-6-1.97048e-8im
│  0.000435027-8.28725e-19im     -2.63499e-6+4.62331e-8im
│ 
│ 
│ ```
│ 
│ Subexpression:
│ 
│ res = ContinuousWavelets.cwt(f, c)
│ 
│ Evaluated output:
│ 
│ ┌ Warning: the lowest frequency wavelet has more than 1% its max at zero, so it may not be analytic. Think carefully
│ │   lowAprxAnalyt = 0.061863
│ └ @ ContinuousWavelets ~/.julia/packages/ContinuousWavelets/arobh/src/sanityChecks.jl:7
│ 2047×31 Matrix{ComplexF64}:
│  -1.48637e-6+4.06351e-19im  …  0.000109978+9.67834e-5im
│  -1.48602e-6+8.29936e-19im     -8.24922e-5+0.000130656im
│             ⋮               ⋱             ⋮
│  0.000435175+2.74268e-19im  …  -2.47195e-6-1.97048e-8im
│  0.000435027-7.22511e-19im     -2.63499e-6+4.62331e-8im
│ 
│ Expected output:
│ 
│ ┌ Warning: the lowest frequency wavelet has more than 1% its max at zero, so it may not be analytic. Think carefully
│ │   lowAprxAnalyt = 0.061863
│ └ @ ContinuousWavelets ~/work/ContinuousWavelets.jl/ContinuousWavelets.jl/src/sanityChecks.jl:6
│ 2047×31 Matrix{ComplexF64}:
│  -1.48637e-6+3.8241e-19im   …  0.000109978+9.67834e-5im
│  -1.48602e-6+5.15534e-19im     -8.24922e-5+0.000130656im
│             ⋮               ⋱             ⋮
│  0.000435175+2.30636e-19im  …  -2.47195e-6-1.97048e-8im
│  0.000435027-8.28725e-19im     -2.63499e-6+4.62331e-8im
│ 
│   diff =
│    ┌ Warning: the lowest frequency wavelet has more than 1% its max at zero, so it may not be analytic. Think carefully
│    │   lowAprxAnalyt = 0.061863
│    └ @ ContinuousWavelets ~/work/ContinuousWavelets.jl/ContinuousWavelets.jl/src/sanityChecks.jl:6
│    ~/.julia/packages/ContinuousWavelets/arobh/src/sanityChecks.jl:7
│    2047×31 Matrix{ComplexF64}:
│     -1.48637e-6+3.8241e-19im   -1.48637e-6+4.06351e-19im  …  0.000109978+9.67834e-5im
│     -1.48602e-6+5.15534e-19im     -1.48602e-6+8.29936e-19im     -8.24922e-5+0.000130656im
│                ⋮               ⋱             ⋮
│     0.000435175+2.30636e-19im  0.000435175+2.74268e-19im  …  -2.47195e-6-1.97048e-8im
│     0.000435027-8.28725e-19im     0.000435027-7.22511e-19im     -2.63499e-6+4.62331e-8im
└ @ Documenter.DocTests ~/.julia/packages/ContinuousWavelets/arobh/docs/src/README.md:30
┌ Error: doctest failure in ~/.julia/packages/ContinuousWavelets/arobh/docs/src/README.md:77-100
│ 
│ ```jldoctest ex
│ using ContinuousWavelets, Wavelets
│ f = testfunction(n, "Bumps");
│ c = wavelet(dog2, β = 2)
│ res = ContinuousWavelets.cwt(f, c)
│ # dropping the middle peaks
│ res[620:1100, :] .= 0
│ # and smoothing the remaining peaks
│ res[:, 10:end] .= 0
│ freqs = ContinuousWavelets.getMeanFreq(length(f), c)
│ dropped = ContinuousWavelets.icwt(res, c, DualFrames())
│ round.(dropped,sigdigits=12)
│ 
│ # output
│ 
│ ┌ Warning: the canonical dual frame is off by 3.81e6, consider using one of the delta dual frames
│ └ @ ContinuousWavelets ~/work/ContinuousWavelets.jl/ContinuousWavelets.jl/src/sanityChecks.jl:41
│ 2047-element Vector{Float64}:
│  0.0069417253841
│  0.00694223965946
│  ⋮
│  0.00268854944484
│  0.00268852311536
│ ```
│ 
│ Subexpression:
│ 
│ using ContinuousWavelets, Wavelets
│ f = testfunction(n, "Bumps");
│ c = wavelet(dog2, β = 2)
│ res = ContinuousWavelets.cwt(f, c)
│ # dropping the middle peaks
│ res[620:1100, :] .= 0
│ # and smoothing the remaining peaks
│ res[:, 10:end] .= 0
│ freqs = ContinuousWavelets.getMeanFreq(length(f), c)
│ dropped = ContinuousWavelets.icwt(res, c, DualFrames())
│ round.(dropped,sigdigits=12)
│ 
│ Evaluated output:
│ 
│ ┌ Warning: the canonical dual frame is off by 3.81e6, consider using one of the delta dual frames
│ └ @ ContinuousWavelets ~/.julia/packages/ContinuousWavelets/arobh/src/sanityChecks.jl:41
│ 2047-element Vector{Float64}:
│  0.0069417253841
│  0.00694223965946
│  ⋮
│  0.00268854944484
│  0.00268852311535
│ 
│ Expected output:
│ 
│ ┌ Warning: the canonical dual frame is off by 3.81e6, consider using one of the delta dual frames
│ └ @ ContinuousWavelets ~/work/ContinuousWavelets.jl/ContinuousWavelets.jl/src/sanityChecks.jl:41
│ 2047-element Vector{Float64}:
│  0.0069417253841
│  0.00694223965946
│  ⋮
│  0.00268854944484
│  0.00268852311536
│ 
│   diff =
│    ┌ Warning: the canonical dual frame is off by 3.81e6, consider using one of the delta dual frames
│    └ @ ContinuousWavelets ~/work/ContinuousWavelets.jl/ContinuousWavelets.jl/src/sanityChecks.jl:41
│    ~/.julia/packages/ContinuousWavelets/arobh/src/sanityChecks.jl:41
│    2047-element Vector{Float64}:
│     0.0069417253841
│     0.00694223965946
│     ⋮
│     0.00268854944484
│     0.002688523115360.00268852311535
└ @ Documenter.DocTests ~/.julia/packages/ContinuousWavelets/arobh/docs/src/README.md:77
CWT{Continuous db2, Father Wavelet, Q=8.0, β=2.0,aveLen=0.0, frame=1.0, norm=Inf, extraOctaves=0.0}┌ Error: doctest failure in ~/.julia/packages/ContinuousWavelets/arobh/docs/src/README.md:104-143
│ 
│ ```jldoctest ex
│ julia> using Wavelets
│ 
│ julia> exs = cat(testfunction(n, "Doppler"), testfunction(n, "Blocks"), testfunction(n, "Bumps"), testfunction(n, "HeaviSine"), dims=2);
│ 
│ julia> c = wavelet(cDb2, β=2, extraOctaves=-0)
│ 
│ julia> res = circshift(ContinuousWavelets.cwt(exs, c), (0, 1, 0))
│ ┌ Warning: the highest frequency wavelet has more than 1% its max at the end, so it may not be analytic. Think carefully
│ │   highAprxAnalyt = 0.26778
│ └ @ ContinuousWavelets ~/work/ContinuousWavelets.jl/ContinuousWavelets.jl/src/sanityChecks.jl:12
│ 2047×32×4 Array{Float64, 3}:
│ [:, :, 1] =
│  1.89367e-5  0.000266033  …  4.6727e-5    2.99983e-6
│  8.33321e-5  0.000266913     1.56557e-5  -4.46419e-5
│  ⋮                        ⋱  ⋮
│  2.24677e-6  0.00198709   …  4.24042e-6   3.80685e-6
│  2.63848e-6  0.00198004      4.3791e-6    3.47575e-6
│ 
│ [:, :, 2] =
│   7.81007e-18  0.0226754  0.00955729  …   3.68809e-18
│  -3.47114e-18  0.022684   0.00950443     -3.47114e-18
│   ⋮                                   ⋱
│  -9.29595e-18  0.0341512  0.0108039   …  -3.84208e-19
│   1.27592e-18  0.0342157  0.0107729      -1.7043e-18
│ 
│ [:, :, 3] =
│  -4.2736e-7   0.0059687   …  4.47839e-8  1.86209e-8
│  -4.39691e-7  0.00596762     3.30771e-8  7.78201e-9
│   ⋮                       ⋱  ⋮
│  -9.41123e-8  0.00339924  …  8.01012e-9  4.78652e-9
│  -9.36079e-8  0.0034061      8.3188e-9   4.24252e-9
│ 
│ [:, :, 4] =
│   0.000307454  -0.0150898   -0.00391724  …   0.000301757
│   6.05948e-5   -0.0152536   -0.00405883      8.45503e-5
│   ⋮                                      ⋱
│  -0.000307094  -0.00755439  -0.00156729  …  -0.000594673
│  -0.000378125  -0.00746687  -0.00146262     -0.00051676
│ ```
│ 
│ Subexpression:
│ 
│ res = circshift(ContinuousWavelets.cwt(exs, c), (0, 1, 0))
│ 
│ Evaluated output:
│ 
│ ┌ Warning: the highest frequency wavelet has more than 1% its max at the end, so it may not be analytic. Think carefully
│ │   highAprxAnalyt = 0.26778
│ └ @ ContinuousWavelets ~/.julia/packages/ContinuousWavelets/arobh/src/sanityChecks.jl:12
│ 2047×32×4 Array{Float64, 3}:
│ [:, :, 1] =
│  1.89367e-5  0.000266033  …  4.6727e-5    2.99983e-6
│  8.33321e-5  0.000266913     1.56557e-5  -4.46419e-5
│  ⋮                        ⋱  ⋮
│  2.24677e-6  0.00198709   …  4.24042e-6   3.80685e-6
│  2.63848e-6  0.00198004      4.3791e-6    3.47575e-6
│ 
│ [:, :, 2] =
│  5.20671e-18  0.0226754  …  1.73557e-18   1.51862e-18
│  6.94228e-18  0.022684      1.73557e-18   3.47114e-18
│  ⋮                       ⋱  ⋮
│  5.52775e-18  0.0341512  …  4.66141e-18  -1.81278e-18
│  5.202e-18    0.0342157     6.79498e-18  -2.35239e-18
│ 
│ [:, :, 3] =
│  -4.2736e-7   0.0059687   …  4.47839e-8  1.86209e-8
│  -4.39691e-7  0.00596762     3.30771e-8  7.78201e-9
│   ⋮                       ⋱  ⋮
│  -9.41123e-8  0.00339924  …  8.01012e-9  4.78652e-9
│  -9.36079e-8  0.0034061      8.3188e-9   4.24252e-9
│ 
│ [:, :, 4] =
│   0.000307454  -0.0150898   -0.00391724  …   0.000301757
│   6.05948e-5   -0.0152536   -0.00405883      8.45503e-5
│   ⋮                                      ⋱
│  -0.000307094  -0.00755439  -0.00156729  …  -0.000594673
│  -0.000378125  -0.00746687  -0.00146262     -0.00051676
│ 
│ Expected output:
│ 
│ ┌ Warning: the highest frequency wavelet has more than 1% its max at the end, so it may not be analytic. Think carefully
│ │   highAprxAnalyt = 0.26778
│ └ @ ContinuousWavelets ~/work/ContinuousWavelets.jl/ContinuousWavelets.jl/src/sanityChecks.jl:12
│ 2047×32×4 Array{Float64, 3}:
│ [:, :, 1] =
│  1.89367e-5  0.000266033  …  4.6727e-5    2.99983e-6
│  8.33321e-5  0.000266913     1.56557e-5  -4.46419e-5
│  ⋮                        ⋱  ⋮
│  2.24677e-6  0.00198709   …  4.24042e-6   3.80685e-6
│  2.63848e-6  0.00198004      4.3791e-6    3.47575e-6
│ 
│ [:, :, 2] =
│   7.81007e-18  0.0226754  0.00955729  …   3.68809e-18
│  -3.47114e-18  0.022684   0.00950443     -3.47114e-18
│   ⋮                                   ⋱
│  -9.29595e-18  0.0341512  0.0108039   …  -3.84208e-19
│   1.27592e-18  0.0342157  0.0107729      -1.7043e-18
│ 
│ [:, :, 3] =
│  -4.2736e-7   0.0059687   …  4.47839e-8  1.86209e-8
│  -4.39691e-7  0.00596762     3.30771e-8  7.78201e-9
│   ⋮                       ⋱  ⋮
│  -9.41123e-8  0.00339924  …  8.01012e-9  4.78652e-9
│  -9.36079e-8  0.0034061      8.3188e-9   4.24252e-9
│ 
│ [:, :, 4] =
│   0.000307454  -0.0150898   -0.00391724  …   0.000301757
│   6.05948e-5   -0.0152536   -0.00405883      8.45503e-5
│   ⋮                                      ⋱
│  -0.000307094  -0.00755439  -0.00156729  …  -0.000594673
│  -0.000378125  -0.00746687  -0.00146262     -0.00051676
│ 
│   diff =
│    ┌ Warning: the highest frequency wavelet has more than 1% its max at the end, so it may not be analytic. Think carefully
│    │   highAprxAnalyt = 0.26778
│    └ @ ContinuousWavelets ~/work/ContinuousWavelets.jl/ContinuousWavelets.jl/src/sanityChecks.jl:12
│    ~/.julia/packages/ContinuousWavelets/arobh/src/sanityChecks.jl:12
│    2047×32×4 Array{Float64, 3}:
│    [:, :, 1] =
│     1.89367e-5  0.000266033  …  4.6727e-5    2.99983e-6
│     8.33321e-5  0.000266913     1.56557e-5  -4.46419e-5
│     ⋮                        ⋱  ⋮
│     2.24677e-6  0.00198709   …  4.24042e-6   3.80685e-6
│     2.63848e-6  0.00198004      4.3791e-6    3.47575e-6
│    
│    [:, :, 2] =
│      7.81007e-18  =
│     5.20671e-18  0.0226754  0.00955729  …   3.68809e-18
│     -3.47114e-18  0.022684   0.00950443     -3.47114e-18
│      ⋮                                   ⋱
│     -9.29595e-18  …  1.73557e-18   1.51862e-18
│     6.94228e-18  0.022684      1.73557e-18   3.47114e-18
│     ⋮                       ⋱  ⋮
│     5.52775e-18  0.0341512  0.0108039   …  -3.84208e-19
│      1.27592e-18  0.0342157  0.0107729      -1.7043e-18
│    
│    4.66141e-18  -1.81278e-18
│     5.202e-18    0.0342157     6.79498e-18  -2.35239e-18
│    
│    [:, :, 3] =
│     -4.2736e-7   0.0059687   …  4.47839e-8  1.86209e-8
│     -4.39691e-7  0.00596762     3.30771e-8  7.78201e-9
│      ⋮                       ⋱  ⋮
│     -9.41123e-8  0.00339924  …  8.01012e-9  4.78652e-9
│     -9.36079e-8  0.0034061      8.3188e-9   4.24252e-9
│    
│    [:, :, 4] =
│      0.000307454  -0.0150898   -0.00391724  …   0.000301757
│      6.05948e-5   -0.0152536   -0.00405883      8.45503e-5
│      ⋮                                      ⋱
│     -0.000307094  -0.00755439  -0.00156729  …  -0.000594673
│     -0.000378125  -0.00746687  -0.00146262     -0.00051676
└ @ Documenter.DocTests ~/.julia/packages/ContinuousWavelets/arobh/docs/src/README.md:104
CWT{Morlet mean 6.283185307179586, Father Wavelet, Q=8.0, β=2.0,aveLen=0.0, frame=1.0, norm=Inf, extraOctaves=0.0}┌ Error: doctest failure in ~/.julia/packages/ContinuousWavelets/arobh/src/utils.jl:453-480
│ 
│ ```jldoctest
│ julia> using ContinuousWavelets, Random
│ 
│ julia> rng = MersenneTwister(23425); Y = randn(rng, 2053, 4);
│ 
│ julia> X = Y .+ 3;
│ 
│ julia> c = wavelet(morl, β = 2)
│ 
│ julia> Xspec = crossSpectrum(X, Y, c); size(Xspec)
│ (2053, 29, 4, 4)
│ 
│ julia> Xspec[:,:,1,1]
│ 2053×29 Matrix{ComplexF64}:
│  -4.14517e-5+2.19692e-20im  …  1.19877e-5-7.07215e-15im
│  -4.14157e-5+2.23209e-21im     1.19896e-5-7.06562e-15im
│             ⋮               ⋱
│  0.000119144+4.38332e-21im     1.70054e-5+1.85809e-15im
│  0.000119178+1.3884e-20im      1.69993e-5+1.8598e-15im
│ 
│ julia> Xspec[:,:,1,2]
│ 2053×29 Matrix{ComplexF64}:
│   5.42995e-5-1.94343e-20im  …    2.649e-6-1.22869e-6im
│    5.4303e-5-1.52994e-20im      2.6479e-6-1.23329e-6im
│             ⋮               ⋱
│  -3.17457e-5-1.12611e-20im     4.71683e-6+3.72814e-6im
│  -3.17719e-5+1.44436e-20im     4.71417e-6+3.7279e-6im
│ 
│ ```
│ 
│ Subexpression:
│ 
│ Xspec[:,:,1,1]
│ 
│ Evaluated output:
│ 
│ 2053×29 Matrix{ComplexF64}:
│  -4.14517e-5-1.18296e-20im  …  1.19877e-5-7.07216e-15im
│  -4.14157e-5-2.46485e-20im     1.19896e-5-7.06563e-15im
│             ⋮               ⋱
│  0.000119144+1.27274e-20im     1.70054e-5+1.85809e-15im
│  0.000119178+7.09791e-21im     1.69993e-5+1.85979e-15im
│ 
│ Expected output:
│ 
│ 2053×29 Matrix{ComplexF64}:
│  -4.14517e-5+2.19692e-20im  …  1.19877e-5-7.07215e-15im
│  -4.14157e-5+2.23209e-21im     1.19896e-5-7.06562e-15im
│             ⋮               ⋱
│  0.000119144+4.38332e-21im     1.70054e-5+1.85809e-15im
│  0.000119178+1.3884e-20im      1.69993e-5+1.8598e-15im
│ 
│   diff =
│    2053×29 Matrix{ComplexF64}:
│     -4.14517e-5+2.19692e-20im  -4.14517e-5-1.18296e-20im  …  1.19877e-5-7.07215e-15im
│     -4.14157e-5+2.23209e-21im     1.19896e-5-7.06562e-15im
│                1.19877e-5-7.07216e-15im
│     -4.14157e-5-2.46485e-20im     1.19896e-5-7.06563e-15im
│                ⋮               ⋱
│     0.000119144+4.38332e-21im     0.000119144+1.27274e-20im     1.70054e-5+1.85809e-15im
│     0.000119178+1.3884e-20im      1.69993e-5+1.8598e-15im0.000119178+7.09791e-21im     1.69993e-5+1.85979e-15im
└ @ Documenter.DocTests ~/.julia/packages/ContinuousWavelets/arobh/src/utils.jl:453
┌ Error: doctest failure in ~/.julia/packages/ContinuousWavelets/arobh/src/utils.jl:453-480
│ 
│ ```jldoctest
│ julia> using ContinuousWavelets, Random
│ 
│ julia> rng = MersenneTwister(23425); Y = randn(rng, 2053, 4);
│ 
│ julia> X = Y .+ 3;
│ 
│ julia> c = wavelet(morl, β = 2)
│ 
│ julia> Xspec = crossSpectrum(X, Y, c); size(Xspec)
│ (2053, 29, 4, 4)
│ 
│ julia> Xspec[:,:,1,1]
│ 2053×29 Matrix{ComplexF64}:
│  -4.14517e-5+2.19692e-20im  …  1.19877e-5-7.07215e-15im
│  -4.14157e-5+2.23209e-21im     1.19896e-5-7.06562e-15im
│             ⋮               ⋱
│  0.000119144+4.38332e-21im     1.70054e-5+1.85809e-15im
│  0.000119178+1.3884e-20im      1.69993e-5+1.8598e-15im
│ 
│ julia> Xspec[:,:,1,2]
│ 2053×29 Matrix{ComplexF64}:
│   5.42995e-5-1.94343e-20im  …    2.649e-6-1.22869e-6im
│    5.4303e-5-1.52994e-20im      2.6479e-6-1.23329e-6im
│             ⋮               ⋱
│  -3.17457e-5-1.12611e-20im     4.71683e-6+3.72814e-6im
│  -3.17719e-5+1.44436e-20im     4.71417e-6+3.7279e-6im
│ 
│ ```
│ 
│ Subexpression:
│ 
│ Xspec[:,:,1,2]
│ 
│ Evaluated output:
│ 
│ 2053×29 Matrix{ComplexF64}:
│   5.42995e-5-1.09846e-20im  …    2.649e-6-1.22869e-6im
│    5.4303e-5+3.60853e-20im      2.6479e-6-1.23329e-6im
│             ⋮               ⋱
│  -3.17457e-5-1.1214e-21im      4.71683e-6+3.72814e-6im
│  -3.17719e-5-2.02166e-20im     4.71417e-6+3.7279e-6im
│ 
│ Expected output:
│ 
│ 2053×29 Matrix{ComplexF64}:
│   5.42995e-5-1.94343e-20im  …    2.649e-6-1.22869e-6im
│    5.4303e-5-1.52994e-20im      2.6479e-6-1.23329e-6im
│             ⋮               ⋱
│  -3.17457e-5-1.12611e-20im     4.71683e-6+3.72814e-6im
│  -3.17719e-5+1.44436e-20im     4.71417e-6+3.7279e-6im
│ 
│   diff =
│    2053×29 Matrix{ComplexF64}:
│      5.42995e-5-1.94343e-20im  5.42995e-5-1.09846e-20im  …    2.649e-6-1.22869e-6im
│       5.4303e-5-1.52994e-20im      5.4303e-5+3.60853e-20im      2.6479e-6-1.23329e-6im
│                ⋮               ⋱
│     -3.17457e-5-1.12611e-20im     -3.17457e-5-1.1214e-21im      4.71683e-6+3.72814e-6im
│     -3.17719e-5+1.44436e-20im     -3.17719e-5-2.02166e-20im     4.71417e-6+3.7279e-6im
└ @ Documenter.DocTests ~/.julia/packages/ContinuousWavelets/arobh/src/utils.jl:453
CWT{Morlet mean 6.283185307179586, Father Wavelet, Q=8.0, β=2.0,aveLen=0.0, frame=1.0, norm=Inf, extraOctaves=0.0}┌ Error: Doctesting failed
│   exception =
│    `makedocs` encountered a doctest error. Terminating build
│    Stacktrace:
│      [1] error(s::String)
│        @ Base ./error.jl:35
│      [2] runner(#unused#::Type{Documenter.Builder.Doctest}, doc::Documenter.Documents.Document)
│        @ Documenter.Builder ~/.julia/packages/Documenter/H5y27/src/Builder.jl:216
│      [3] dispatch(#unused#::Type{Documenter.Builder.DocumentPipeline}, x::Documenter.Documents.Document)
│        @ Documenter.Utilities.Selectors ~/.julia/packages/Documenter/H5y27/src/Utilities/Selectors.jl:170
│      [4] #2
│        @ ~/.julia/packages/Documenter/H5y27/src/Documenter.jl:273 [inlined]
│      [5] cd(f::Documenter.var"#2#3"{Documenter.Documents.Document}, dir::String)
│        @ Base.Filesystem ./file.jl:112
│      [6] makedocs(; debug::Bool, format::Documenter.Writers.HTMLWriter.HTML, kwargs::Base.Pairs{Symbol, Any, NTuple{6, Symbol}, NamedTuple{(:root, :source, :sitename, :doctest, :modules, :doctestfilters), Tuple{String, String, String, Symbol, Vector{Module}, Vector{Regex}}}})
│        @ Documenter ~/.julia/packages/Documenter/H5y27/src/Documenter.jl:272
│      [7] (::Documenter.var"#all_doctests#32"{Bool, Vector{Regex}, Vector{Module}})()
│        @ Documenter ~/.julia/packages/Documenter/H5y27/src/Documenter.jl:942
│      [8] macro expansion
│        @ /Applications/Julia-1.9.app/Contents/Resources/julia/share/julia/stdlib/v1.9/Test/src/Test.jl:478 [inlined]
│      [9] macro expansion
│        @ ~/.julia/packages/Documenter/H5y27/src/Documenter.jl:963 [inlined]
│     [10] macro expansion
│        @ /Applications/Julia-1.9.app/Contents/Resources/julia/share/julia/stdlib/v1.9/Test/src/Test.jl:1498 [inlined]
│     [11] doctest(source::String, modules::Vector{Module}; fix::Bool, testset::String, doctestfilters::Vector{Regex})
│        @ Documenter ~/.julia/packages/Documenter/H5y27/src/Documenter.jl:963
│     [12] doctest
│        @ ~/.julia/packages/Documenter/H5y27/src/Documenter.jl:927 [inlined]
│     [13] doctest(package::Module; manual::Bool, testset::Nothing, kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
│        @ Documenter ~/.julia/packages/Documenter/H5y27/src/Documenter.jl:898
│     [14] doctest(package::Module)
│        @ Documenter ~/.julia/packages/Documenter/H5y27/src/Documenter.jl:884
│     [15] macro expansion
│        @ ~/.julia/packages/ContinuousWavelets/arobh/test/runtests.jl:8 [inlined]
│     [16] macro expansion
│        @ /Applications/Julia-1.9.app/Contents/Resources/julia/share/julia/stdlib/v1.9/Test/src/Test.jl:1498 [inlined]
│     [17] top-level scope
│        @ ~/.julia/packages/ContinuousWavelets/arobh/test/runtests.jl:8
│     [18] include(fname::String)
│        @ Base.MainInclude ./client.jl:478
│     [19] top-level scope
│        @ none:6
│     [20] eval
│        @ ./boot.jl:370 [inlined]
│     [21] exec_options(opts::Base.JLOptions)
│        @ Base ./client.jl:280
│     [22] _start()
│        @ Base ./client.jl:522
└ @ Documenter ~/.julia/packages/Documenter/H5y27/src/Documenter.jl:952
Doctests: ContinuousWavelets: Test Failed at ~/.julia/packages/Documenter/H5y27/src/Documenter.jl:963
  Expression: all_doctests()

Stacktrace:
 [1] macro expansion
   @ /Applications/Julia-1.9.app/Contents/Resources/julia/share/julia/stdlib/v1.9/Test/src/Test.jl:478 [inlined]
 [2] macro expansion
   @ ~/.julia/packages/Documenter/H5y27/src/Documenter.jl:963 [inlined]
 [3] macro expansion
   @ /Applications/Julia-1.9.app/Contents/Resources/julia/share/julia/stdlib/v1.9/Test/src/Test.jl:1498 [inlined]
 [4] doctest(source::String, modules::Vector{Module}; fix::Bool, testset::String, doctestfilters::Vector{Regex})
   @ Documenter ~/.julia/packages/Documenter/H5y27/src/Documenter.jl:963
┌ Warning: the lowest frequency wavelet has more than 1% its max at zero, so it may not be analytic. Think carefully
│   lowAprxAnalyt = 0.038173
└ @ ContinuousWavelets ~/.julia/packages/ContinuousWavelets/arobh/src/sanityChecks.jl:7
┌ Warning: there are wavelets whose peaks are far enough apart that the trough between them is less than half the height of the highest frequency wavelet
│   minimalRegionComparedToLastPeak = 6.4278
└ @ ContinuousWavelets ~/.julia/packages/ContinuousWavelets/arobh/src/sanityChecks.jl:32
┌ Warning: the lowest frequency wavelet has more than 1% its max at zero, so it may not be analytic. Think carefully
│   lowAprxAnalyt = 0.038173
└ @ ContinuousWavelets ~/.julia/packages/ContinuousWavelets/arobh/src/sanityChecks.jl:7
┌ Warning: there are wavelets whose peaks are far enough apart that the trough between them is less than half the height of the highest frequency wavelet
│   minimalRegionComparedToLastPeak = 6.4278
└ @ ContinuousWavelets ~/.julia/packages/ContinuousWavelets/arobh/src/sanityChecks.jl:32
Test Summary:                  | Pass  Fail  Total     Time
ContinuousWavelets.jl          | 5005     1   5006  1m06.5s
  Doctests: ContinuousWavelets |          1      1    24.4s
  Construction Types           | 2700         2700    19.3s
  Delta Spikes                 |   12           12     0.4s
  Coherence and Cross spectrum |    3            3     1.5s
  Wavelet properties           | 2266         2266    10.5s
  Inversion                    |   24           24     9.2s
ERROR: LoadError: Some tests did not pass: 5005 passed, 1 failed, 0 errored, 0 broken.
in expression starting at ~/.julia/packages/ContinuousWavelets/arobh/test/runtests.jl:7
ERROR: Package ContinuousWavelets errored during testing

Feature request: cross wavelet tranform

Hi,

Thanks for sharing this package!

I am currently learning about wavelets and their practical usage in Julia. Based I what I've learned so far, the wavelet related functionalities currently in Julia are limited compared to more mature toolboxes like in MATLAB.

One thing I'm wondering specifically is the cross wavelet transform, or wavelet coherence described here. Is it possible to quickly implement a similar method within this package?

Continuous Wavelet Transform Crashes for Complex Inputs

My use case for wavelets involves analyzing complex baseband signals like chirps and tones.
This crashes the wavelet transform, e.g.

 yt = cwt(chirp, wave)
┌ Warning: the lowest frequency wavelet has more than 1% its max at zero, so it may not be analytic. Think carefully
│   lowAprxAnalyt = 0.050211
└ @ ContinuousWavelets ~/.julia/packages/ContinuousWavelets/pycif/src/sanityChecks.jl:7
ERROR: DimensionMismatch: arrays could not be broadcast to a common size; got a dimension with lengths 4096 and 2049
Stacktrace:
  [1] _bcs1
    @ ./broadcast.jl:555 [inlined]
  [2] _bcs
    @ ./broadcast.jl:549 [inlined]
  [3] broadcast_shape
    @ ./broadcast.jl:543 [inlined]
  [4] combine_axes
    @ ./broadcast.jl:524 [inlined]
  [5] instantiate
    @ ./broadcast.jl:306 [inlined]
  [6] materialize
    @ ./broadcast.jl:903 [inlined]
  [7] analyticTransformComplex!(wave::Array{…}, daughters::Matrix{…}, x̂::Matrix{…}, fftPlan::FFTW.cFFTWPlan{…}, averagingType::NoAve)
    @ ContinuousWavelets ~/.julia/packages/ContinuousWavelets/pycif/src/apply.jl:172
  [8] cwt(Y::Vector{…}, cWav::CWT{…}, daughters::Matrix{…}, fftPlans::Int64)
    @ ContinuousWavelets ~/.julia/packages/ContinuousWavelets/pycif/src/apply.jl:56
  [9] cwt
    @ ~/.julia/packages/ContinuousWavelets/pycif/src/apply.jl:23 [inlined]
 [10] #cwt#21
    @ ~/.julia/packages/ContinuousWavelets/pycif/src/apply.jl:240 [inlined]
 [11] cwt(Y::Vector{ComplexF64}, c::CWT{SymBoundary, Float64, Morlet, Float64, true})
    @ ContinuousWavelets ~/.julia/packages/ContinuousWavelets/pycif/src/apply.jl:236
 [12] top-level scope
    @ /data/projects/Airanaculus/GPSSignalClass/signalclass.jl:38
Some type information was truncated. Use `show(err)` to see complete types.

chirp is a length 2048 complex chirp signal.

I think I can work around this by separately taking the cwt() operation of the real and imaginary parts, but I don't see why these transforms don't work out of the box on a complex vector.

Cone of influence

Hello,

I am very excited to see the scaleogram demos from continuous wavelet transform!

One step further, I would love to see the addition of the cone of influence on top of the scaleogram. When searching through the source codes, I found one function caveats which returns coi as the 3rd argument:

function caveats(n1, c::CWT{W}; J1::Int64=-1, dt::S=1/1000, s0::V=NaN) where {S<:Real, W<:WaveletBoundary, V <: Real}

However, there is currently no test or example of calling this function.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.