-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathHaar1Orthogonal.cs
235 lines (228 loc) · 9.56 KB
/
Haar1Orthogonal.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
///
/// SharpWave - A refactored port of JWave
/// https://github.com/graetz23/JWave
///
/// MIT License
///
/// Copyright (c) 2020-2024 Christian ([email protected])
///
/// Permission is hereby granted, free of charge, to any person obtaining a copy
/// of this software and associated documentation files (the "Software"), to deal
/// in the Software without restriction, including without limitation the rights
/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
/// copies of the Software, and to permit persons to whom the Software is
/// furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included in all
/// copies or substantial portions of the Software.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
/// SOFTWARE.
///
namespace SharpWave
{
///<summary>
/// Alfred Haar's orthogonal wavelet transform.
///
/// Remarks on mathematics (perpendicular, orthogonal, and orthonormal):
///
/// "Orthogonal" is used for (base) vectors which are "perpendicular" but of
/// any length.
/// "Orthonormal" is used for (base) vectors which are "perpendicular" and of
/// a "unit" length of one.
///
/// "Orthogonal" system; ASCII art does not display the angles in 90 deg
/// or int 45 deg correctly:
///
/// ^ y
/// |
/// 1 + . scaling function
/// | / {1,1} \
/// | / | length = 1.4142135623730951
/// |/ / = sqrt( (1)^2 + (1)^2 )
/// --o------+-> x
/// 0 |\ 1 \
/// | \ | length = 1.4142135623730951
/// | \ / = sqrt( (1)^2 + (-1)^2 )
/// -1 + . wavelet function
/// | {1,-1}
///
/// One can see that by each step of the algorithm the input coefficient's
/// "energy" (energy := ||.||_2 euclidean norm) rises, while ever input value
/// is multiplied by 1.414213 (sqrt(2)). This rise of the energy has to be
/// corrected by reducing the added "energy" or "energ delta by the reverse
/// transform method. For this example the multiplying factor is 1/2.
///
/// Therefore, the "energy correction" factor is added by a private member
/// variable (_energyCorrectionFactor) and the reverse transform is
/// overwritten; see forward reverse methods of this class.
///
/// For more details abour the introduced euclidean norm; see wikipedia:
/// http:///en.wikipedia.org/wiki/Euclidean_norm
///
/// The main disadvantage using "orthogonal" wavelets are the generated
/// wavelet sub spaces having different levels of "energy". Those can not be
/// combined anymore easily. For each level a different energy correction
/// factor would get necessary depending on the target wavelet space.
/// If an "orthonormal" wavelet is taken, the ||.||_2 norm does not change
/// any energy at any level of the generated wavelet sub spaces. This allows
/// for combining wavelet sub spaces of different levels easily and opens
/// the application for enegy based algorithms, e.g. like iterative solvers
/// used for wavelet compressed system of linear equations.
///
/// Some other common used orthogonal Haar coefficients are:
///
/// Reducing energy in wach wavelet sub space:
/// _scalingDeCom[ 0 ] = .5; /// s0
/// _scalingDeCom[ 1 ] = .5; /// s1
///
/// _waveletDeCom[ 0 ] = .5; /// w0 = s1
/// _waveletDeCom[ 1 ] = -.5; /// w1 = -s0
///
/// _scalingReCon[ 0 ] = .5; /// s0
/// _scalingReCon[ 1 ] = .5; /// s1
///
/// _waveletReCon[ 0 ] = .5; /// w0 = s1
/// _waveletReCon[ 1 ] = -.5; /// w1 = -s0
///
/// The ||.||_2 norm will shrink the energy compared to the input signal's
/// norm, due to length sqrt( .5 * .5 + .5 * .5 ) = sqrt( .5 ) = .7071.
/// Hence, the correction factor in the reverse method is exchanged from:
/// 1/2 = .5 to the value of 2.!
///
/// For example a 2-D input matrix is defined in time domain as:
/// 1 1 1 1
/// 1 1 1 1
/// 1 1 1 1
/// 1 1 1 1
///
/// The orthogonal version of the Haar wavelet will result in some beautiful
/// hilbert domain using Fast Wavelet or Wavelet Packet Transform:
/// 16 0 0 0
/// 0 0 0 0
/// 0 0 0 0
/// 0 0 0 0
/// One can see that all energy is just summed up which looks fine but gets
/// complicated to correlate, if an application has the need to deal in
/// different wavelet sub spaces, Hibert sub domains, respectively.
///
/// For reconstruction the energy correction by 1/2 gets necessary and
/// results (in case of no rounding errors; e.g. 0.999999999999) in:
/// 1 1 1 1
/// 1 1 1 1
/// 1 1 1 1
/// 1 1 1 1
///
/// Such orthogonal wavelets can be used for any application always dealing
/// with all levels of the sub spaces or for checking wheater some changed
/// or new transform algorithm is working properly.
///
/// An alternative is to use coefficients keeping the correction implicitely:
///
/// _scalingDeCom[ 0 ] = 1.; /// s_d0
/// _scalingDeCom[ 1 ] = 1.; /// s_d1
///
/// _waveletDeCom[ 0 ] = 1.; /// w_d0 = s_d1
/// _waveletDeCom[ 1 ] = -1.; /// w_d1 = -s_d0
///
/// _scalingReCon[ 0 ] = .5; /// s_r0
/// _scalingReCon[ 1 ] = .5; /// s_r1
///
/// _waveletReCon[ 0 ] = .5; /// w_r0 = s_r1
/// _waveletReCon[ 1 ] = -.5; /// w_r1 = -s_r0
///
/// or
///
/// _scalingDeCom[ 0 ] = .5; /// s_d0
/// _scalingDeCom[ 1 ] = .5; /// s_d1
///
/// _waveletDeCom[ 0 ] = .5; /// w_d0 = s_d1
/// _waveletDeCom[ 1 ] = -.5; /// w_d1 = -s_d0
///
/// _scalingReCon[ 0 ] = 2.; /// s_r0
/// _scalingReCon[ 1 ] = 2.; /// s_r1
///
/// _waveletReCon[ 0 ] = 2.; /// w_r0 = s_r1
/// _waveletReCon[ 1 ] = -2.; /// w_r1 = -s_r0
///
/// .. have fun ~8>
///</summary>
///<remarks>
/// Christian ([email protected]) 03.06.2010 09:47:24
///</remarks>
public class Haar1Orthogonal : Wavelet {
///<summary>
/// Energy correction factor of the (overwritten) reverse transform.
///</summary>
///<remarks>
/// Christian ([email protected]) 03.06.2010 09:47:24
///</remarks>
private static double _energyCorrectionFactor = .5;
///<summary>
/// Constructor setting up the orthogonal Haar scaling coefficients and
/// matching wavelet coefficients. However, the reverse method has to be
/// obverloaded, due to having to change the energy during reconstruction.
///</summary>
///<remarks>
/// Christian ([email protected]) 03.06.2010 09:47:24
///</remarks>
public Haar1Orthogonal( ) :base("Haar 1 orthogonal", 2, 2) {
// Orthogonal wavelet coefficients; NOT orthonormal, missing sqrt(2.)
_scalingDeCom = new double[ _motherWavelength ];
_scalingDeCom[ 0 ] = 1.0; // w0
_scalingDeCom[ 1 ] = 1.0; // w1
// Rule for constructing an orthogonal vector in R^2 -- scales
_waveletDeCom = new double[ _motherWavelength ];
_waveletDeCom[ 0 ] = _scalingDeCom[ 1 ]; // w1
_waveletDeCom[ 1 ] = -_scalingDeCom[ 0 ]; // -w0
// Copy to reconstruction filters due to orthogonality
_scalingReCon = new double[ _motherWavelength ];
_waveletReCon = new double[ _motherWavelength ];
for( int i = 0; i < _motherWavelength; i++ ) {
_scalingReCon[ i ] = _scalingDeCom[ i ];
_waveletReCon[ i ] = _waveletDeCom[ i ];
} // i
} // Haar1
///<summary>
/// The reverse wavelet transform using the Alfred Haar's wavelet. The arrHilb
/// array keeping coefficients of Hilbert domain should be of length 2 to the
/// power of p -- length = 2^p where p is a positive integer. But in case of an
/// only orthogonal Haar wavelet the reverse transform has to have a factor of
/// 0.5 to reduce the up sampled "energy" in Hilbert space.
///</summary>
///<remarks>
/// Christian ([email protected]) 15.02.2014 21:17:22
///</remarks>
override public double[ ] reverse( double[ ] arrHilb, int arrHilbLength ) {
double[ ] arrTime = new double[ arrHilbLength ];
int length = arrTime.Length;
for( int i = 0; i < length; i++ ) {
arrTime[ i ] = 0.0;
} // rows
int h = length >> 1; // .. -> 8 -> 4 -> 2 ..
for( int i = 0; i < h; i++ ) {
for( int j = 0; j < _motherWavelength; j++ ) {
int k = ( i * 2 ) + j; // int k = ( i << 1 ) + j;
while( k >= length ) {
k -= length; // circulate arrays if scaling and wavelet are larger
} // circuate
// adding up energy from scaling coefficients, the low pass
// (approximation) filter, and wavelet coefficients, the high pass
// filter (details). However, the raised energy has to be reduced by
// half for each step because of vectorial length of each base vector
// of the orthogonal system is of sqrt( 2. ).
arrTime[ k ] +=
_energyCorrectionFactor * // reduction of added energy by 1/2 ..
( ( arrHilb[ i ] * _scalingReCon[ j ] ) +
( arrHilb[ i + h ] * _waveletReCon[ j ] ) );
} // reconstruction from { scaling coefficients | wavelet coefficients }
} // h = 2^(p-1) | p = { 1, 2, .., N } .. shrink by half wavelength
return arrTime;
} // reverse
} // Haar1Orthogonal
} // namespace