module DiscreteWavelet.Lifting where {- ghci -lgslcblas -lgsl -i:../math:../gslmatrix/ ../gslmatrix/gslaux.o ShiftedSignal.hs DiscreteWavelet.Lifting -} import LinearAlgebra.Matrix(Matrix,matrix,matrix_x_matrix) import Numerics.SpecialFunctions (factorial, recipBinomial, binomial) import qualified ShiftedSignal as SS {- * Lifting steps for weighting of channels -} skewAdditionMatrix :: Double -> Matrix skewAdditionMatrix x = matrix [[x,1],[1,0]] additionWeightingGeneric :: Double -> Double -> [Double] additionWeightingGeneric a x = let b = (x-1)/a in reverse [a, b, -a/x, -b*x] additionWeightingRational :: Double -> [Double] additionWeightingRational x = reverse [1, x-1, -1/x, x*(1-x)] -- does not work for x>1 additionWeightingOptimal :: Double -> [Double] additionWeightingOptimal x = let steps y = let q = sqrt((1-y)/(2+y)) p = sqrt((1-y)*(2+y)) s = sqrt y in [-p*s, q/s, p/s, -q*s] in if x<=1 then reverse (steps x) else map negate (steps (recip x)) testAdditions :: [Double] -> Matrix testAdditions xs = foldl1 matrix_x_matrix (map skewAdditionMatrix xs) {- * Lifting steps for CDF lowpasses, allowing also fractional orders -} {- | If the lifting sequence is reversed it can be used to construct the lowpass or the highpass independent from the other filter. This function generates a list of modified liftings steps where the target filter of convolve-accumulate operation is also weighted. This sequence was designed for the forward application order but when applied in reversed order it does not work. -} cdfHalfLiftingSeqEven :: Fractional a => a -> [(a, SS.T a)] cdfHalfLiftingSeqEven n = tail $ zip (zipWith (*) (iterate (subtract 2) (2*n)) (iterate (2+) 0)) (zipWith SS.translate (cycle [-1,0]) (map (SS.fromList . replicate 2) (iterate (subtract 2) (n+1)))) {- | Do some modified lifting steps where the target filter is weighted. -} noUpsampleWeightLifting2 :: Num a => [(a, SS.T a)] -> (SS.T a, SS.T a) -> [(SS.T a, SS.T a)] noUpsampleWeightLifting2 lseq start = scanl (\(x, y) (k, s) -> (y, SS.superpose (SS.amplify k y) (SS.convolve s x))) start lseq {- | Generate lifting filters for CDF low-pass of even order. They are designed in a way that also allows fractional orders but the sequence of lifted filters does not converge. -} cdfLiftingSeqEvenFrac :: Double -> [SS.T Double] cdfLiftingSeqEvenFrac n = zipWith SS.translate (cycle [0,-1]) (map (\c -> SS.fromList [c,c]) (cdfLiftingSeqEvenFracCoeffs n)) cdfLiftingSeqEvenFracCoeffs :: Double -> [Double] cdfLiftingSeqEvenFracCoeffs n = let am = recipBinomial (n/2-0.5) 0.5 / 2 modds = iterate (subtract 2) (n-1) mevens = iterate (subtract 1) (n/2-1) as = scanl (\ai m -> recip ((n^(2::Int) - 4 * m^(2::Int)) * ai)) am mevens in zipWith (*) modds as {- factorial (n/2-1) / (4 * factorial (n/2-0.5) / factorial (-0.5)) == factorial (n/2-1) * factorial (-0.5) / (4 * factorial (n/2-0.5)) == factorial (n/2-1) * factorial 0.5 / (2 * factorial (n/2-0.5)) -} {- The lowpass as it evolves from lifting steps -} cdfLiftingEvenFracLowpass :: Double -> [SS.T Double] cdfLiftingEvenFracLowpass n = map (SS.interleave . (\(x,y) -> [y,x])) (scanl (flip SS.noUpsampleLiftingStep2) (SS.fromScalar 1, SS.fromScalar 0) (cdfLiftingSeqEvenFrac n)) {- mapM (\x -> plotList [] (ShiftedSignal.signal (ShiftedSignal.multiRefine 6 2 x (ShiftedSignal.fromScalar 1)))) (take 10 $ ShiftedSignal.cdfLiftingEvenFracLowpass 4.3) -}