/**
* JWave - Java implementation of wavelet transform algorithms
*
* Copyright 2010-2012 Christian Scheiblich
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file Haar02Orthogonal.java is part of JWave.
*
* @author Christian Scheiblich
* date 03.06.2010 09:47:24
* contact graetz@mailfish.de
*/
package math.transform.jwave.handlers.wavelets;
/**
* Alfred Haar's orthogonal wavelet transform.
*
* @date 03.06.2010 09:47:24
* @author Christian Scheiblich
*/
public class Haar02Orthogonal extends Wavelet {
/**
* Constructor setting up the orthogonal Haar wavelet coeffs and the scales;
*
* @date 03.06.2010 09:47:24
* @author Christian Scheiblich
*/
public Haar02Orthogonal( ) {
_waveLength = 2;
_coeffs = new double[ _waveLength ]; // can be done in static way also; faster?
// Orthogonal wavelet coefficients; NOT orthonormal, due to missing sqrt(2.)
_coeffs[ 0 ] = 1.; // w0
_coeffs[ 1 ] = -1.; // w1
_scales = new double[ _waveLength ]; // can be done in static way also; faster?
// Rule for constructing an orthogonal vector in R^2 -- scales
_scales[ 0 ] = -_coeffs[ 1 ]; // -w1
_scales[ 1 ] = _coeffs[ 0 ]; // w0
//
// Remark on mathematics (perpendicular, orthogonal, and orthonormal):
//
// "Orthogonal" is used for vectors which are perpendicular but of any length.
// "Orthonormal" is used for vectors which are perpendicular and of a unit length of one.
//
//
// "Orthogonal" system -- ASCII art does not display the angles in 90 deg (or 45 deg):
//
// ^ 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 coefficients "energy"
// (energy := ||.||_2 euclidean norm) rises, while ever input value is multiplied
// by 1.414213 (sqrt(2)). However, one has to correct this change of "energy" in
// the reverse transform by adding the factor 1/2 .
//
// (see http://en.wikipedia.org/wiki/Euclidean_norm for the euclidean norm)
//
// The main disadvantage using an "orthogonal" wavelet is that the generated wavelet
// sub spaces of different size and/or level can not be combined anymore easily, due
// to their differing "energy" or norm (||.||_2). If an "orthonormal" wavelet is
// taken, the ||.||_2 norm does not change at any size or any transform level. This
// allows for combining wavelet sub spaces of different dimension or even level.
// Also possible coefficients -> change forward and reverse functions in common
// _coeffs[ 0 ] = .5; // w0
// _coeffs[ 1 ] = -.5; // w1
// _scales[ 0 ] = -_coeffs[ 1 ]; // -w1
// _scales[ 1 ] = _coeffs[ 0 ]; // w0
// The ||.||_2 norm will shrink compared to the input signal's norm.
} // Haar02
/**
* The forward wavelet transform using the Alfred Haar's wavelet. The arrTime
* array keeping coefficients of time domain should be of length 2 to the
* power of p -- length = 2^p where p is a positive integer.
*
* @date 03.06.2010 09:47:24
* @author Christian Scheiblich
* @see math.transform.jwave.handlers.wavelets.Wavelet#forward(double[])
*/
@Override
public double[ ] forward( double[ ] arrTime ) {
double[ ] arrHilb = new double[ arrTime.length ];
int k = 0;
int h = arrTime.length >> 1;
for( int i = 0; i < h; i++ ) {
for( int j = 0; j < _waveLength; j++ ) {
k = ( i << 1 ) + j;
if( k >= arrTime.length )
k -= arrTime.length;
arrHilb[ i ] += arrTime[ k ] * _scales[ j ]; // low pass filter - energy
arrHilb[ i + h ] += arrTime[ k ] * _coeffs[ j ]; // high pass filter - details
// by each summation, "energy" is added, due to the orthogonal Haar Wavelet.
} // wavelet
} // h
return arrHilb;
} // forward
/**
* 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" ion Hilbert space.
*
* @date 03.06.2010 09:47:24
* @author Christian Scheiblich
* @see math.transform.jwave.handlers.wavelets.Wavelet#reverse(double[])
*/
@Override
public double[ ] reverse( double[ ] arrHilb ) {
double[ ] arrTime = new double[ arrHilb.length ];
int k = 0;
int h = arrHilb.length >> 1;
for( int i = 0; i < h; i++ ) {
for( int j = 0; j < _waveLength; j++ ) {
k = ( i << 1 ) + j;
if( k >= arrHilb.length )
k -= arrHilb.length;
arrTime[ k ] += ( arrHilb[ i ] * _scales[ j ] + arrHilb[ i + h ]
* _coeffs[ j ] ); // adding up details times energy
// The factor .5 gets necessary here to reduce the added "energy" of the forward method
arrTime[ k ] *= .5; // correction of the up sampled "energy" -- ||.||_2 euclidean norm
} // wavelet
} // h
return arrTime;
} // reverse
} // class