From e3a43fd457db47d92fb9720d85a5e05aae606330 Mon Sep 17 00:00:00 2001 From: Zeng Fung Liew Date: Sat, 4 Dec 2021 00:41:06 -0800 Subject: [PATCH] Update API documentations for LDB. Update API documentation organization. --- README.md | 28 +----- docs/make.jl | 2 +- docs/src/api/acwt.md | 12 +-- docs/src/api/bestbasis.md | 20 ++-- docs/src/api/denoising.md | 2 - docs/src/api/dwt.md | 8 +- docs/src/api/swt.md | 8 +- docs/src/api/utils.md | 12 +-- docs/src/manual/transforms.md | 2 +- src/mod/LDB.jl | 170 ++++++++++++++++++++++++++++------ src/mod/Visualizations.jl | 28 ++---- 11 files changed, 181 insertions(+), 111 deletions(-) diff --git a/README.md b/README.md index 31221da..f657afb 100644 --- a/README.md +++ b/README.md @@ -29,34 +29,14 @@ Extension). It contains additional functionalities that complement Wavelets.jl, ## Authors This package is written and maintained by Zeng Fung Liew and Shozen Dan under the supervision of Professor Naoki Saito at the University of California, Davis. +## What's New (v0.1.13) +- **Changes in supported types in `denoise` and `denoiseall` functions.** For the `inputtype` positional argument, the initially supported arguments `:acwt` and `:acwpt` are now changed to `:acdwt` and `:acwpd` to match the function name change in `WaveletsExt.ACWT`. +- **2D Local Discriminant Basis now supported.** 2D version of LDB is now up and running without any changes in the syntax compared to the 1D version. + ## What's New (v0.1.12) - **Bug fixes on best basis algorithms** to allow compatibility when partial wavelet decomposition is run. - **New function `plot_tfbdry2()` implemented.** Visual representation of leaf nodes for 2D best basis trees now available. -## What's New (v0.1.11) -- **All types of 2D wavelet transforms up and running.** Discrete wavelet transforms, wavelet packet transforms, and wavelet packet decompositions for standard, autocorrelation, and stationary transforms working well with improved speeds and memory allocations. -- **2D best basis algorithms up and running.** Best basis algorithms such as standard best basis, joint best basis (JBB), and least statistically dependent basis (LSDB) now support 2D wavelet transforms. - -## What's New (v0.1.10) -- **Direct support for wavelet transform of multiple signals.** Since the current package deals - a lot with multiple signals (eg. Joint Best Basis (JBB), group signal denoising, Local - Discriminant Basis (LDB)), functions are added to transform all signals at once, allowing - for simpler, cleaner and more efficient implementation of transforms for multiple signals. -- **2D wavelet transforms.** 2D wavelet packet transforms and 2D wavelet packet - decompositions are implemented, along with additional functions to navigate through the quadtree. -- **Improved API documentations.** API documentations contain more explanations for each - function argument and more examples of function use cases. -- **Standardization of function names.** Wavelet transform function names are standardized - to: - - Discrete wavelet transform (redundant and non-redundant versions) have functions that - end with `dwt`, eg. `dwt`, `sdwt`, `acdwt`. - - Wavelet packet transform (redundant and non-redundant versions), where only the - coefficients of the leaf nodes are kept, have functions that end with `wpt`, eg. - `wpt`, `acwpt`, `swpt`. - - Wavelet packet decomposition (redundant and non-redundant versions), where all - coefficients of each level are recorded, have functions that end with `wpd`, eg. - `wpd`, `acwpd`, `swpd`. - ## Installation The package is part of the official Julia Registry. It can be install via the Julia REPL. ```julia diff --git a/docs/make.jl b/docs/make.jl index 2802460..b7e4abd 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -19,10 +19,10 @@ makedocs( "DWT" => "api/dwt.md", "ACWT" => "api/acwt.md", "SWT" => "api/swt.md", + "SIWPD" => "api/siwpd.md", "Best Basis" => "api/bestbasis.md", "Denoising" => "api/denoising.md", "LDB" => "api/ldb.md", - "SIWPD" => "api/siwpd.md", "Utils" => "api/utils.md", "Visualizations" => "api/visualizations.md", ] diff --git a/docs/src/api/acwt.md b/docs/src/api/acwt.md index 4bae013..b019ac0 100644 --- a/docs/src/api/acwt.md +++ b/docs/src/api/acwt.md @@ -4,8 +4,7 @@ Modules = [ACWT] ``` -## Public API -### Transforms on 1 Signal +## Transforms on 1 Signal ```@docs ACWT.acdwt ACWT.acdwt! @@ -21,9 +20,7 @@ ACWT.iacwpd ACWT.iacwpd! ``` -### Transforms on Multiple Signals -!!! note - The following functions currently only support 1D-signals. Transforms on multiple 2D-signals are not yet supported. +## Transforms on Multiple Signals ```@docs ACWT.acdwtall ACWT.iacdwtall @@ -33,8 +30,7 @@ ACWT.acwpdall ACWT.iacwpdall ``` -## Private API -### Utilities +## Utilities ```@docs ACWT.autocorr ACWT.pfilter @@ -43,7 +39,7 @@ ACWT.make_acqmfpair ACWT.make_acreverseqmfpair ``` -### Single Step Transforms +## Single Step Transforms ```@docs ACWT.acdwt_step ACWT.acdwt_step! diff --git a/docs/src/api/bestbasis.md b/docs/src/api/bestbasis.md index a8f101a..2d323f4 100644 --- a/docs/src/api/bestbasis.md +++ b/docs/src/api/bestbasis.md @@ -4,8 +4,7 @@ Modules = [BestBasis] ``` -## Public API -### Cost functions and computations +## Cost functions and computations ```@docs BestBasis.CostFunction BestBasis.LSDBCost @@ -21,7 +20,14 @@ BestBasis.tree_costs BestBasis.tree_costs(::AbstractMatrix{T}, ::AbstractVector{BitVector}, ::SIBB) where T<:Number ``` -### Best basis computation +# Best Basis Tree Selection +```@docs +BestBasis.bestbasis_treeselection +BestBasis.bestbasis_treeselection(::AbstractVector{Tc}, ::AbstractVector{Tt}) where {Tc<:AbstractVector{<:Union{Number,Nothing}}, Tt<:BitVector} +BestBasis.delete_subtree! +``` + +## Best basis computation ```@docs BestBasis.BestBasisType BestBasis.LSDB @@ -32,11 +38,3 @@ Wavelets.Threshold.bestbasistree Wavelets.Threshold.bestbasistree(::AbstractMatrix{T}, ::Integer, ::SIBB) where T<:Number BestBasis.bestbasistreeall ``` - -# Private API -```@docs -BestBasis.bestbasis_treeselection -BestBasis.bestbasis_treeselection(::AbstractVector{Tc}, ::AbstractVector{Tt}) where {Tc<:AbstractVector{<:Union{Number,Nothing}}, Tt<:BitVector} -BestBasis.delete_subtree! - -``` \ No newline at end of file diff --git a/docs/src/api/denoising.md b/docs/src/api/denoising.md index f8e0bb2..3229540 100644 --- a/docs/src/api/denoising.md +++ b/docs/src/api/denoising.md @@ -4,7 +4,6 @@ Modules = [Denoising] ``` -# Public API ## Shrinking Types and Constructors ```@docs Denoising.RelErrorShrink @@ -25,7 +24,6 @@ Wavelets.Threshold.denoise Denoising.denoiseall ``` -# Private API ## Helper Functions for Threshold Determination and Noise Estimation ```@docs Denoising.surethreshold diff --git a/docs/src/api/dwt.md b/docs/src/api/dwt.md index a158f4d..0b31ed8 100644 --- a/docs/src/api/dwt.md +++ b/docs/src/api/dwt.md @@ -4,8 +4,7 @@ Modules = [DWT] ``` -## Public API -### Transforms on 1 Signal +## Transforms on 1 Signal ```@docs Wavelets.Transforms.wpt Wavelets.Transforms.wpt(::AbstractArray{T,2}, ::OrthoFilter, ::Integer; ::Bool) where T<:Number @@ -21,7 +20,7 @@ DWT.iwpd DWT.iwpd! ``` -### Transforms on Multiple Signals +## Transforms on Multiple Signals ```@docs DWT.dwtall DWT.idwtall @@ -31,8 +30,7 @@ DWT.wpdall DWT.iwpdall ``` -## Private API -### Single Step Transforms +## Single Step Transforms ```@docs DWT.dwt_step DWT.dwt_step! diff --git a/docs/src/api/swt.md b/docs/src/api/swt.md index 9ebf0dc..6cf8ee2 100644 --- a/docs/src/api/swt.md +++ b/docs/src/api/swt.md @@ -4,8 +4,7 @@ Modules = [SWT] ``` -## Public API -### Transforms on 1 Signal +## Transforms on 1 Signal ```@docs SWT.sdwt SWT.sdwt! @@ -21,7 +20,7 @@ SWT.iswpd SWT.iswpd! ``` -### Transforms on Multiple Signals +## Transforms on Multiple Signals ```@docs SWT.sdwtall SWT.isdwtall @@ -31,8 +30,7 @@ SWT.swpdall SWT.iswpdall ``` -## Private API -### Single Step Transforms +## Single Step Transforms ```@docs SWT.sdwt_step SWT.sdwt_step! diff --git a/docs/src/api/utils.md b/docs/src/api/utils.md index a5340ea..083fe6e 100644 --- a/docs/src/api/utils.md +++ b/docs/src/api/utils.md @@ -4,8 +4,7 @@ Modules = [Utils] ``` -## Public API -### Useful wavelet/signal utilities +## Useful wavelet/signal utilities ```@docs Wavelets.Util.maxtransformlevels Utils.getbasiscoef @@ -17,7 +16,7 @@ Utils.coarsestscalingrange Utils.finestdetailrange ``` -### Tree traversing functions +## Tree traversing functions ```@docs Wavelets.Util.isvalidtree Wavelets.Util.maketree @@ -28,7 +27,7 @@ Utils.getdepth Utils.gettreelength ``` -### Metrics +## Metrics ```@docs Utils.relativenorm Utils.psnr @@ -36,7 +35,7 @@ Utils.snr Utils.ssim ``` -### Dataset generation +## Dataset generation ```@docs Utils.ClassData Utils.duplicatesignals @@ -44,8 +43,7 @@ Utils.generatesignals Utils.generateclassdata ``` -## Private API +## Miscellaneous ```@docs Utils.main2depthshift -Utils.packet ``` \ No newline at end of file diff --git a/docs/src/manual/transforms.md b/docs/src/manual/transforms.md index 0ee5a76..1a34593 100644 --- a/docs/src/manual/transforms.md +++ b/docs/src/manual/transforms.md @@ -118,7 +118,7 @@ plot(p0, p1, p2, layout=(1,3)) - 2D Example ```@example dwt -using Images, TestImages +using TestImages img = testimage("cameraman"); x = convert(Array{Float64}, img); diff --git a/src/mod/LDB.jl b/src/mod/LDB.jl index 33a3ba9..ad5825a 100644 --- a/src/mod/LDB.jl +++ b/src/mod/LDB.jl @@ -1,5 +1,4 @@ module LDB -using Base: AbstractFloat export # energy map EnergyMap, @@ -73,9 +72,9 @@ following field values: - `n_features::Union{Integer, Nothing}`: (Default: `nothing`) the dimension of output after undergoing feature selection and transformation. - `sz::Union{Vector{T} where T<:Integer, Nothing}`: (Default: `nothing`) Size of signal -- `Γ::Union{AbstractArray{<:AbstractFloat}, AbstractArray{NamedTuple{(:coef, :weight), - Tuple{S1, S2}}} where {S1<:Array{T} where T<:AbstractFloat, S2<:Union{T, Array{T}} where - T<:AbstractFloat}, Nothing}`: (Default: `nothing`) computed energy map +- `Γ::Union{AbstractArray{T} where T<:AbstractFloat, AbstractArray{NamedTuple{(:coef, + :weight), Tuple{S₁, S₂}}} where {S₁<:Array{T} where T<:AbstractFloat, S2<:Union{T, + Array{T}} where T<:AbstractFloat}, Nothing}`: (Default: `nothing`) computed energy map - `DM::Union{AbstractArray{<:AbstractFloat}, Nothing}`: (Default: `nothing`) computed discriminant measure - `cost::Union{AbstractVector{<:AbstractFloat}, Nothing}`: (Default: `nothing`) computed @@ -113,8 +112,26 @@ end """ fit!(f, X, y) -Fits the Local Discriminant Basis feature selection algorithm `f` onto the signals `X` (or -the decomposed signals `Xw`) with labels `y`. +Fits the Local Discriminant Basis feature selection algorithm `f` onto the signals `X` with +labels `y`. + +# Arguments +- `f::LocalDiscriminantBasis`: Local discriminant basis object. +- `X::AbstractArray{S} where S<:AbstractFloat`: Group of signals of the same size, arranged + in the 2nd (1D signals) or 3rd (2D signals) dimension. +- `y::AbstractVector{T} where T`: Labels corresponding to each signal in X. + +# Returns +- `f::LocalDiscriminantBasis`: The same LDB object `f` with updated fields. + +# Examples +```julia +using Wavelets, WaveletsExt + +X, y = generateclassdata(ClassData(:tri, 5, 5, 5)) +f = LocalDiscriminantBasis() +fit!(f, X, y) +``` **See also:** [`LocalDiscriminantBasis`](@ref), [`fit_transform`](@ref), [`transform`](@ref), [`inverse_transform`](@ref), [`change_nfeatures`](@ref) @@ -140,6 +157,31 @@ end """ fitdec!(f, Xw, y) + +Fits the Local Discriminant Basis feature selection algorithm `f` onto the decomposed +signals `Xw` with labels `y`. + +# Arguments +- `f::LocalDiscriminantBasis`: Local discriminant basis object. +- `Xw::AbstractArray{S} where S<:AbstractFloat`: Group of decomposed signals of the same + size, arranged in the 3rd (1D signals) or 4th (2D signals) dimension. +- `y::AbstractVector{T} where T`: Labels corresponding to each signal in X. + +# Returns +- `f::LocalDiscriminantBasis`: The same LDB object `f` with updated fields. + +# Examples +```julia +using Wavelets, WaveletsExt + +X, y = generateclassdata(ClassData(:tri, 5, 5, 5)) +f = LocalDiscriminantBasis() +Xw = wpdall(X, f.wt) +fitdec!(f, Xw, y) +``` + +**See also:** [`LocalDiscriminantBasis`](@ref), [`fit!`](@ref), [`fit_transform`](@ref), + [`transform`](@ref), [`inverse_transform`](@ref), [`change_nfeatures`](@ref) """ function fitdec!(f::LocalDiscriminantBasis, Xw::AbstractArray{S}, y::AbstractVector{T}) where {S<:AbstractFloat, T} @@ -211,10 +253,30 @@ end """ transform(f, X) -Extract the LDB features on signals `X`. +Extract the LDB features from signals `X` based on the LDB tree constructed from previously +fitted signals. + +# Arguments +- `f::LocalDiscriminantBasis`: Local discriminant basis object. +- `X::AbstractArray{S} where S<:AbstractFloat`: Group of signals of the same size, arranged + in the 2nd (1D signals) or 3rd (2D signals) dimension. -**See also:** [`LocalDiscriminantBasis`](@ref), [`fit!`](@ref), - [`fit_transform`](@ref), [`inverse_transform`](@ref), [`change_nfeatures`](@ref) +# Returns +- `Xc::Matrix{S}`: A matrix of the extracted LDB features from `X`, where each column + corresponds to the coefficients extracted from the corresponding signal. + +# Examples +```julia +using Wavelets, WaveletsExt + +X, y = generateclassdata(ClassData(:tri, 5, 5, 5)) +f = LocalDiscriminantBasis() +fit!(f, X, y) +Xc = transform(f, X) +``` + +**See also:** [`LocalDiscriminantBasis`](@ref), [`fit!`](@ref), [`fit_transform`](@ref), + [`inverse_transform`](@ref), [`change_nfeatures`](@ref) """ function transform(f::LocalDiscriminantBasis, X::AbstractArray{T}) where T # check necessary measurements @@ -250,10 +312,33 @@ end """ fit_transform(f, X, y) -Fit and transform the signals `X` with labels `y` based on the LDB class `f`. - -**See also:** [`LocalDiscriminantBasis`](@ref), [`fit!`](@ref), - [`transform`](@ref), [`inverse_transform`](@ref), [`change_nfeatures`](@ref) +Fit and transform the signals `X` with labels `y` based on the LDB class `f`. This function +essentially combines both `fit!` and `transform` into one, and is the preferred method when +trying to extract the LDB coefficients of the training dataset. For the test dataset, one +needs to first run `fit!` on the training dataset before running `transform` on the test +dataset. + +# Arguments +- `f::LocalDiscriminantBasis`: Local discriminant basis object. +- `Xw::AbstractArray{S} where S<:AbstractFloat`: Group of decomposed signals of the same + size, arranged in the 3rd (1D signals) or 4th (2D signals) dimension. +- `y::AbstractVector{T} where T`: Labels corresponding to each signal in X. + +# Returns +- `Xc::Matrix{S}`: A matrix of the extracted LDB features from `X`, where each column + corresponds to the coefficients extracted from the corresponding signal. + +# Examples +```julia +using Wavelets, WaveletsExt + +X, y = generateclassdata(ClassData(:tri, 5, 5, 5)) +f = LocalDiscriminantBasis() +Xc = fit_transform(f, X, y) +``` + +**See also:** [`LocalDiscriminantBasis`](@ref), [`fit!`](@ref), [`transform`](@ref), + [`inverse_transform`](@ref), [`change_nfeatures`](@ref) """ function fit_transform(f::LocalDiscriminantBasis, X::AbstractArray{S}, @@ -282,11 +367,29 @@ end """ inverse_transform(f, X) -Compute the inverse transform on the feature matrix `x` to form the original -signal based on the LDB class `f`. +Compute the inverse transform on the feature matrix `X` to form the original signal based on +the LDB class `f`. This function can be used to reconstruct the signals and compare the +reconstructed features between different classes. -**See also:** [`LocalDiscriminantBasis`](@ref), [`fit!`](@ref), - [`fit_transform`](@ref), [`transform`](@ref), [`change_nfeatures`](@ref) +# Arguments +- `f::LocalDiscriminantBasis`: Local discriminant basis object. +- `X::Matrix{S} where S<:AbstractFloat`: A matrix of the extracted LDB features from + original signals, where each column corresponds to the coefficients extracted from the + corresponding signal. + +# Returns +- `Xₜ::Array{S}`: Reconstructed signals. + +# Examples +```julia +X, y = generateclassdata(ClassData(:tri, 5, 5, 5)) +f = LocalDiscriminantBasis() +Xc = fit_transform(f, X, y) +Xₜ = inverse_transform(f, Xc) +``` + +**See also:** [`LocalDiscriminantBasis`](@ref), [`fit!`](@ref), [`fit_transform`](@ref), + [`transform`](@ref), [`change_nfeatures`](@ref) """ function inverse_transform(f::LocalDiscriminantBasis, X::AbstractArray{T,2}) where T<:AbstractFloat @@ -310,18 +413,31 @@ end """ change_nfeatures(f, x, n_features) -Change the number of features from `f.n_features` to `n_features`. +Change the number of features extracted from the signals from `f.n_features` to +`n_features`. + +!!! warning If the input `n_features` is larger than `f.n_features`, it results in the + regeneration of signals based on the current `f.n_features` before reselecting the + features. This will cause additional features to be less accurate and effective. Often + times, the "additional" features tend to be zeros. + +# Arguments +- `f::LocalDiscriminantBasis`: Local discriminant basis object. +- `x::AbstractMatrix{S} where S<:AbstractFloat`: A matrix of the extracted LDB features from + original signals, where each column corresponds to the coefficients extracted from the + corresponding signal. +- `n_features::Integer`: Desired number of features in selected by LDB. -Note that if the input `n_features` is larger than `f.n_features`, it results in -the regeneration of signals based on the current `f.n_features` before -reselecting the features. This will cause additional features to be less -accurate and effective. +# Returns +- `xₜ::Matrix{S}`: Matrix of extracted LDB features, where the number of rows is now + `n_features` instead of the previous `f.n_features`. **See also:** [`LocalDiscriminantBasis`](@ref), [`fit!`](@ref), [`fit_transform`](@ref), [`transform`](@ref), [`inverse_transform`](@ref) """ -function change_nfeatures(f::LocalDiscriminantBasis, x::AbstractArray{T,2}, - n_features::Integer) where T<:Number +function change_nfeatures(f::LocalDiscriminantBasis, + x::AbstractArray{T,2}, + n_features::Integer) where T<:AbstractFloat # check measurements @assert !isnothing(f.n_features) @@ -331,14 +447,14 @@ function change_nfeatures(f::LocalDiscriminantBasis, x::AbstractArray{T,2}, # change number of features if f.n_features ≥ n_features f.n_features = n_features - y = x[1:f.n_features,:] + xₜ = x[1:f.n_features,:] else @warn "Proposed n_features larger than currently saved n_features. Results will be less accurate since inverse_transform and transform is involved." X = inverse_transform(f, x) f.n_features = n_features - y = transform(f, X) + xₜ = transform(f, X) end - return y + return xₜ end end # end module diff --git a/src/mod/Visualizations.jl b/src/mod/Visualizations.jl index 5c3dc4a..1621076 100644 --- a/src/mod/Visualizations.jl +++ b/src/mod/Visualizations.jl @@ -49,10 +49,11 @@ o o # Examples ```@repl -using Wavelets, WaveletsExt +using Wavelets +import WaveletsExt: treenodes_matrix tree = maketree(8, 3, :dwt) -WaveletsExt.Visualizations.treenodes_matrix(tree) +treenodes_matrix(tree) ``` """ function treenodes_matrix(x::BitVector) @@ -171,7 +172,7 @@ tree = maketree(128, 128, 7, :dwt) plot_tfbdry2(tree) ``` -**See also:* [`plot_tfbdry`](@ref) +**See also:** [`plot_tfbdry`](@ref) """ plot_tfbdry2(tree::BitVector) = plot_tfbdry2(tree, 2^(getdepth(length(tree),:quad)+1)) plot_tfbdry2(tree::BitVector, n::Integer) = plot_tfbdry2(tree, n, n) @@ -209,30 +210,17 @@ function plot_tfbdry2(tree::BitVector, n::T, m::T) where T<:Integer end """ - wiggle(wav[; taxis, zaxis, sc, EdgeColor, FaceColor, Orient, Overlap, ZDir]) - wiggle(plt, wav[; taxis, zaxis, sc, EdgeColor, FaceColor, Orient, Overlap, ZDir]) + wiggle(args...[; kwargs...]) + wiggle(plt, args...[; kwargs...]) Plots a set of shaded wiggles. # Arguments - `plt::Plots.Plot`: Input plot to plot shaded wiggles. -- `wav::AbstractArray{<:Number,2}`: Matrix of waveform columns. +- `args...`: Additional positional arguments for `wiggle`. See [`wiggle!`](@ref). # Keyword Arguments -- `taxis::AbstractVector`: (Default: `1:size(wav,1)`) Time axis vector -- `zaxis::AbstractVector`: (Default: `1:size(wav,2)`) Space axis vector -- `sc::Real`: (Default: `1`) Scale factor/magnification. -- `EdgeColor::Symbol`: (Default: `:black`) Sets edge of wiggles color. -- `FaceColor::Symbol`: (Default: `:black`) Sets shading color of wiggles. -- `Overlap::Bool`: (Default: `true`) How signals are scaled. - - `true` - Signals overlap (default); - - `false` - Signals are scaled so they do not overlap. -- `Orient::Symbol`: (Default: `:across`) Controls orientation of wiggles. - - `:across` - from left to right - - `:down` - from top to down -- `ZDir::Symbol`: (Default: `:normal`) Direction of space axis. - - `:normal` - First signal at bottom (default) - - `:reverse` - First signal at top. +- `kwargs...`: Keyword arguments for `wiggle`. See [`wiggle!`](@ref). # Returns `::Plots.Plot`: Shaded wiggles on top of current plot object.