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

multilevel wavelet coefficients #61

Open
tapir27 opened this issue Sep 28, 2020 · 3 comments
Open

multilevel wavelet coefficients #61

tapir27 opened this issue Sep 28, 2020 · 3 comments

Comments

@tapir27
Copy link

tapir27 commented Sep 28, 2020

I am sure I am missing something but I when I run dwt I can only see the first level wavelet detail coefficients. How can I see the other levels?

@gummif
Copy link
Member

gummif commented Sep 28, 2020

The return value is a vector of scaling and detail coefficients. Where they are depends on the number of levels specified. There are util functions that can be used to determine the ranges of coefficients.

@staticfloat
Copy link

staticfloat commented Sep 16, 2021

I've been using this utility wrapper:

# Define DyadicLevels; a useful way to iterate over a dyadic signal representation,
# such as that returned from `dwt()`.
struct DyadicLevels
    data::Vector
    max_level::Int

    function DyadicLevels(data::Vector, max_level::Union{Int64,Nothing} = nothing)
        max_possible_level = Wavelets.maxtransformlevels(length(data))
        if max_level === nothing
            max_level = max_possible_level
        elseif max_level > max_possible_level
            throw(ArgumentError("Cannot decompose $(max_level) levels with an input of length $(length(data))"))
        end
        return new(data, max_level)
    end
end

function scalingrange(l::Int, max_level::Int)
    return 1:(l - sum(length(detailrange(l, level)) for level in 1:max_level))
end
scalingrange(x::Vector, max_level::Int) = scalingrange(length(x), max_level)

# Allow easy iteration over the wavelet levels
Base.length(ds::DyadicLevels) = min(Wavelets.maxtransformlevels(length(ds.data)), ds.max_level) + 1
function Base.iterate(ds::DyadicLevels, state=(1,))
    scale_idx = state[1]
    if scale_idx > length(ds)
        return nothing
    end

    next_state = (scale_idx + 1,)
    # Special-case the scaling coefficients as the lowest level:
    if scale_idx == 1
        return ds.data[scalingrange(ds.data, ds.max_level)], next_state
    end

    dyadic_slice = ds.data[detailrange(ds.data, length(ds) - (scale_idx - 1))]
    return dyadic_slice, next_state
end

You can use it with a function like the following, to do a quick-n-dirty plot of your wavelet levels:

function plot_wavelet_levels(x, max_level)
    fig = WGLMakie.Figure()
    ax = WGLMakie.Axis(fig[1,1])

    lines!(ax, x; label="Signal", color="black")
    X = dwt(x, wavelet(WT.db2, WT.Filter), max_level)
    for (level, X_range) in enumerate(DyadicLevels(X, max_level))
        t = (0:(length(X_range)-1))*(length(X)-1)/length(X_range)
        if level == 1
            lines!(ax, t, X_range./4; label="Scaling")
        else
            lines!(ax, t, X_range; label="Detail $(level)")
        end
    end
    
    fig[1,2] = Legend(fig, ax, "Wavelet levels")
    display(fig)
    return nothing
end

@gummif
Copy link
Member

gummif commented Sep 17, 2021

See also utility functions in https://github.com/JuliaDSP/Wavelets.jl/blob/master/src/mod/Util.jl that may be useful.

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

No branches or pull requests

3 participants