2
0
mirror of https://github.com/boostorg/math.git synced 2026-01-19 04:22:09 +00:00

Fix up docs for Daubechies filters [CI SKIP]

This commit is contained in:
Nick Thompson
2020-03-08 09:21:19 -04:00
parent 6f20863719
commit 0b156d9552

View File

@@ -1,5 +1,5 @@
[/ [/
Copyright Nick Thompson, 2020 Copyright Nick Thompson, John Maddock 2020
Distributed under the Boost Software License, Version 1.0. Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt). http://www.boost.org/LICENSE_1_0.txt).
@@ -9,17 +9,17 @@
[h4 Synopsis] [h4 Synopsis]
#include <boost/math/filters/daubechies.hpp> #include <boost/math/filters/daubechies.hpp>
namespace boost::math:filters { namespace boost::math:filters {
template <typename Real, unsigned p> template <typename Real, size_t p>
constexpr std::array<Real, 2*p> daubechies_scaling_filter(); constexpr std::array<Real, 2*p> daubechies_scaling_filter();
template<class Real, size_t p> template<class Real, size_t p>
std::array<Real, 2*p> daubechies_wavelet_filter(); std::array<Real, 2*p> daubechies_wavelet_filter();
} // namespaces } // namespaces
The Daubechies filters provided by Boost.Math return the filter coefficients of the compactly-supported family discovered by Daubechies. The Daubechies filters provided by Boost.Math return the filter coefficients of the compactly-supported family discovered by Daubechies.
@@ -38,21 +38,24 @@ The filters take the number of vanishing moments as a template argument, returni
Numerous notational conventions for the filter coefficients exist. Numerous notational conventions for the filter coefficients exist.
The first ambiguity is whether they should be indexed by the number of vanishing moments, or the number of filter taps. The first ambiguity is whether they should be indexed by the number of vanishing moments, or the number of filter taps.
/Boost.Math indexes the family by the number of vanishing moments./ /Boost.Math indexes the family by the number of vanishing moments./
This indexing convention is the same as PyWavelets and Mathematica, but differs from Numerical Recipes. This indexing convention is the same as PyWavelets and Mathematica, but Numerical Recipes and Wikipedia index by the number of filter taps.
The next ambiguity is the overall scale. The next ambiguity is the overall scale.
We (and PyWavelets) normalize the filters so that their L[sub 2] norm is 1. Boost (and PyWavelets) normalize the filters so that their L[sub 2] norm is 1.
Others normalize so that the L[sub 2] norm is [sqrt]2. Others normalize so that the L[sub 2] norm is [sqrt]2.
Finally, we can use a convolutional representation of the filters, or a dot product representation. Finally, we can use a convolutional representation of the filters, or a dot product representation.
The dot product has all elements reversed relative to the convolutional representation. The dot product has all elements reversed relative to the convolutional representation.
The Boost representation agrees with Table 1 of Daubechies 1988 paper "Orthonormal Bases of Compactly Supported Wavelets",
and Mallat's "A Wavelet Tour of Signal Processing", Table 7.2.
The Boost convention: The Boost convention:
// ... // ...
auto h = boost::math::filters::daubechies_scaling_filter<double, 2>(); constexpr const int p = 2;
auto h = boost::math::filters::daubechies_scaling_filter<double, p>();
std::cout << "h = {" << h[0] << ", " << h[1] << ", " << h[2] << ", " << h[3] << "}\n"; std::cout << "h = {" << h[0] << ", " << h[1] << ", " << h[2] << ", " << h[3] << "}\n";
// output: // output:
h = {0.48296291314453416, 0.83651630373780794, 0.22414386804201339, -0.12940952255126037} h = {0.48296291314453416, 0.83651630373780794, 0.22414386804201339, -0.12940952255126037}
@@ -63,6 +66,7 @@ Mathematica conventions:
WaveletFilterCoefficients[DaubechiesWavelet[2], "PrimalLowpass"] WaveletFilterCoefficients[DaubechiesWavelet[2], "PrimalLowpass"]
{{0, 0.341506}, {1, 0.591506}, {2, 0.158494}, {3, -0.0915064}} {{0, 0.341506}, {1, 0.591506}, {2, 0.158494}, {3, -0.0915064}}
(Multiplying all elements of the Mathematica filter by [sqrt]2 gives the Boost filter.)
PyWavelet conventions: PyWavelet conventions:
@@ -72,14 +76,43 @@ PyWavelet conventions:
>>> np.linalg.norm(pywt.Wavelet('db2').dec_lo) >>> np.linalg.norm(pywt.Wavelet('db2').dec_lo)
1.0 1.0
(Reversing the PyWavelet filter gives the Boost filter.)
The wavelet filters bring additional ambiguity, because they are defined only by being orthogonal to the scaling filter.
So both sign and scale are determined by convention.
For this reason, we demo some other conventions for the wavelet filter as well:
Boost:
auto g = boost::math::filters::daubechies_wavelet_filter<double, p>();
std::cout << "g = {" << g[0] << ", " << g[1] << ", " << g[2] << ", " << g[3] << "}\n";
// output:
g = {-0.12940952255126037, -0.22414386804201339, 0.83651630373780794, -0.48296291314453416}
Mathematica:
WaveletFilterCoefficients[DaubechiesWavelet[2], "PrimalHighpass"]
{{-2, -0.0915064}, {-1, -0.158494}, {0, 0.591506}, {1, -0.341506}}
(Note how Mathematica indexes the filter starting at -2; Boost starts at 0, and the scaling convention is different.)
PyWavelets:
>>> print(pywt.Wavelet('db2').dec_hi)
[-0.48296291314453416, 0.8365163037378079, -0.2241438680420134, -0.12940952255126037]
(Again, reversing the PyWavelets filter gives the Boost filter.)
[h3 Accuracy] [h3 Accuracy]
The filters are accurate to quad precision. The filters are accurate to octuple precision.
[h3 References] [h3 References]
* Ingrid Daubechies, ['Ten Lectures on Wavelets], SIAM Volume 61, 1992 * Ingrid Daubechies, ['Ten Lectures on Wavelets], SIAM Volume 61, 1992
* Ingrid Daubechies, ['Orthonormal bases of compactly supported wavelets], Communications on pure and applied mathematics 41.7 (1988): 909-996.
* Stéphane Mallat. ['A wavelet tour of signal processing.] Elsevier, 1999.
[endsect] [endsect]