hsignal 0.1.2.5 → 0.1.3
raw patch · 6 files changed
+340/−113 lines, 6 filesdep +base-unicode-symbolsPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: base-unicode-symbols
API changes (from Hackage documentation)
+ Numeric.Signal: class Convolvable a
+ Numeric.Signal: class (Storable a, Container Vector a, Num (Vector a), Convert a, Floating (Vector a), RealElement a, Num a) => Filterable a
+ Numeric.Signal: convolve :: (Convolvable a) => a -> a -> a
- Numeric.Signal: analytic_phase :: Vector (Complex Double) -> Vector Double
+ Numeric.Signal: analytic_phase :: (Filterable a, Container Vector a, Double ~ (DoubleOf a)) => Vector (Complex a) -> Vector a
- Numeric.Signal: analytic_power :: Vector (Complex Double) -> Vector Double
+ Numeric.Signal: analytic_power :: (Filterable a) => Vector (Complex Double) -> Vector a
- Numeric.Signal: broadband_filter :: Int -> (Int, Int) -> Vector Double -> Vector Double
+ Numeric.Signal: broadband_filter :: (Filterable a, Double ~ (DoubleOf a), Container Vector (Complex a), Convert (Complex a)) => Int -> (Int, Int) -> Vector a -> Vector a
- Numeric.Signal: broadband_fir :: Int -> (Int, Int) -> Vector Double
+ Numeric.Signal: broadband_fir :: (Filterable a, Double ~ (DoubleOf a), Container Vector (Complex a), Convert (Complex a)) => Int -> (Int, Int) -> Vector a
- Numeric.Signal: deriv :: Vector Double -> Vector Double
+ Numeric.Signal: deriv :: (Filterable a) => Vector a -> Vector a
- Numeric.Signal: downsample :: Int -> Vector Double -> Vector Double
+ Numeric.Signal: downsample :: (Filterable a) => Int -> Vector a -> Vector a
- Numeric.Signal: filter :: Vector Double -> Vector Double -> Int -> Vector Double -> Vector Double
+ Numeric.Signal: filter :: (Filterable a) => Vector a -> Vector a -> Int -> Vector a -> Vector a
- Numeric.Signal: fir :: Int -> [(Double, Double)] -> Int -> Int -> Vector Double -> Vector Double
+ Numeric.Signal: fir :: (Filterable a, Container Vector (Complex a), Convert (Complex a), Double ~ (DoubleOf a)) => Int -> [(a, a)] -> Int -> Int -> Vector a -> Vector a
- Numeric.Signal: freqzF :: Vector Double -> Vector Double -> Int -> Vector Double -> Vector Double
+ Numeric.Signal: freqzF :: (Filterable a, Double ~ (DoubleOf a), Filterable (DoubleOf a)) => Vector a -> Vector a -> Int -> Vector a -> Vector a
- Numeric.Signal: freqzN :: Vector Double -> Vector Double -> Int -> Int -> (Vector Double, Vector Double)
+ Numeric.Signal: freqzN :: (Filterable a, Enum a, Double ~ (DoubleOf a)) => Vector a -> Vector a -> Int -> Int -> (Vector a, Vector a)
- Numeric.Signal: hamming :: Int -> Vector Double
+ Numeric.Signal: hamming :: (Filterable a) => Int -> Vector a
- Numeric.Signal: resize :: Int -> Vector Double -> Vector Double
+ Numeric.Signal: resize :: (Filterable a) => Int -> Vector a -> Vector a
- Numeric.Signal: standard_fir :: Int -> [(Double, Double)] -> Vector Double
+ Numeric.Signal: standard_fir :: (Filterable a, Double ~ (DoubleOf a), Container Vector (Complex a), Convert (Complex a)) => Int -> [(a, a)] -> Vector a
- Numeric.Signal: unwrap :: Vector Double -> Vector Double
+ Numeric.Signal: unwrap :: (Filterable a) => Vector a -> Vector a
- Numeric.Signal.Multichannel: filter :: (Int, Int) -> Multichannel Double -> Multichannel Double
+ Numeric.Signal.Multichannel: filter :: (Filterable a, Double ~ (DoubleOf a), Container Vector (Complex a), Convert (Complex a)) => (Int, Int) -> Multichannel a -> Multichannel a
- Numeric.Signal.Multichannel: mi_phase :: Multichannel Double -> Matrix Double
+ Numeric.Signal.Multichannel: mi_phase :: (Filterable a, Double ~ (DoubleOf a)) => Multichannel a -> Matrix Double
Files
- CHANGES +3/−0
- hsignal.cabal +5/−4
- lib/Numeric/Signal.hs +77/−64
- lib/Numeric/Signal/Internal.hs +172/−38
- lib/Numeric/Signal/Multichannel.hs +5/−3
- lib/Numeric/Signal/signal-aux.c +78/−4
CHANGES view
@@ -48,3 +48,6 @@ 0.1.2.5: hmatrix 0.10.0.0 release++0.1.3:+ Add Float versions of some functions
hsignal.cabal view
@@ -1,5 +1,5 @@ Name: hsignal-Version: 0.1.2.5+Version: 0.1.3 License: BSD3 License-file: LICENSE Author: Vivian McPhail@@ -36,6 +36,7 @@ mtl, array, bytestring, storable-complex, binary,+ base-unicode-symbols, hmatrix >= 0.10.0.0, hmatrix-gsl-stats >= 0.1.2.6, hstatistics >= 0.2.2.5@@ -78,7 +79,7 @@ extra-libraries: extra-lib-dirs: - source-repository head- type: darcs- location: darcs get http://code.haskell.org/hsignal+source-repository head+ type: darcs+ location: http://code.haskell.org/hsignal
lib/Numeric/Signal.hs view
@@ -1,4 +1,6 @@-{-# OPTIONS_GHC -fglasgow-exts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE UnicodeSyntax #-} ----------------------------------------------------------------------------- -- | -- Module : Numeric.Signal@@ -14,6 +16,8 @@ ----------------------------------------------------------------------------- module Numeric.Signal (+ S.Convolvable(..),+ S.Filterable(), -- * Filtering hamming, pwelch,@@ -25,9 +29,9 @@ unwrap, -- * Preprocessing detrend,- downsample,resize,- -- * Utility functions- deriv+ resize,+ downsample,+ deriv, ) where -----------------------------------------------------------------------------@@ -37,7 +41,10 @@ import Numeric.GSL.Fitting.Linear import Data.Complex+import Foreign.Storable() +--import Data.Function.Unicode+ import qualified Data.List as L --import Data.Packed.Vector@@ -51,27 +58,21 @@ ----------------------------------------------------------------------------- -- | filters the signal-filter :: Vector Double -- ^ zero coefficients- -> Vector Double -- ^ pole coefficients- -> Int -- ^ sampling rate- -> Vector Double -- ^ input signal- -> Vector Double -- ^ output signal+filter :: (S.Filterable a) + ⇒ Vector a -- ^ zero coefficients+ -> Vector a -- ^ pole coefficients+ -> Int -- ^ sampling rate+ -> Vector a -- ^ input signal+ -> Vector a -- ^ output signal filter b a s v = let len = dim v w = min s len start = (negate . fromList . reverse . toList . subVector 0 w) v finish = (negate . fromList . reverse . toList . subVector (len-w) w) v v' = join [start,v,finish]- in subVector s len $ S.filter b a v'+ in subVector s len $ S.filter_ b a v' ----------------------------------------------------------------------------- --- | coefficients of a Hamming window-hamming :: Int -- ^ length- -> Vector Double -- ^ the Hamming coeffficents-hamming = S.hamming-------------------------------------------------------------------------------- -- | Welch (1967) power spectrum density using periodogram/FFT method pwelch :: Int -- ^ sampling rate -> Int -- ^ window size@@ -88,9 +89,10 @@ ----------------------------------------------------------------------------- -- | a broadband FIR-broadband_fir :: Int -- ^ sampling rate+broadband_fir :: (S.Filterable a, Double ~ DoubleOf a, Container Vector (Complex a), Convert (Complex a)) ⇒+ Int -- ^ sampling rate -> (Int,Int) -- ^ (lower,upper) frequency cutoff- -> Vector Double -- ^ filter coefficients + -> Vector a -- ^ filter coefficients broadband_fir s (l,h) = let o = 501 ny = (fromIntegral s) / 2.0 fl = (fromIntegral l) / ny@@ -101,21 +103,23 @@ in standard_fir o be -- | a broadband filter-broadband_filter :: Int -- ^ sampling rate- -> (Int,Int) -- ^ (lower,upper) frequency cutoff- -> Vector Double -- ^ input signal- -> Vector Double -- ^ output signal-broadband_filter s f v = let b = broadband_fir s f+broadband_filter :: (S.Filterable a, Double ~ DoubleOf a, Container Vector (Complex a), Convert (Complex a)) + ⇒ Int -- ^ sampling rate+ -> (Int,Int) -- ^ (lower,upper) frequency cutoff+ -> Vector a -- ^ input signal+ -> Vector a -- ^ output signal+broadband_filter s f v = let b = S.fromDouble $ broadband_fir s f in filter b (scalar 1.0) s v ----------------------------------------------------------------------------- -- | standard FIR filter -- | FIR filter with grid a power of 2 greater than the order, ramp = grid/16, hamming window-standard_fir :: Int -> [(Double,Double)] -> Vector Double+standard_fir :: (S.Filterable a, Double ~ DoubleOf a, Container Vector (Complex a), Convert (Complex a)) ⇒ + Int -> [(a,a)] -> Vector a standard_fir o be = let grid = calc_grid o trans = grid `div` 16- in fir o be grid trans $ S.hamming (o+1)+ in fir o be grid trans $ S.hamming_ (o+1) calc_grid :: Int -> Int calc_grid o = let next_power = ceiling (((log $ fromIntegral o) :: Double) / (log 2.0)) :: Int@@ -123,20 +127,22 @@ -- | produce an FIR filter-fir :: Int -- ^ order (one less than the length of the filter)- -> [(Double,Double)] -- ^ band edge frequency, nondecreasing, [0, f1, ..., f(n-1), 1]- -- ^ band edge magnitude+fir :: (S.Filterable a+ , Container Vector (Complex a), Convert (Complex a), Double ~ DoubleOf a) ⇒+ Int -- ^ order (one less than the length of the filter)+ -> [(a,a)] -- ^ band edge frequency, nondecreasing, [0, f1, ..., f(n-1), 1]+ -- ^ band edge magnitude -> Int -- ^ grid spacing -> Int -- ^ transition width- -> Vector Double -- ^ smoothing window (size is order + 1)- -> Vector Double -- ^ the filter coefficients+ -> Vector a -- ^ smoothing window (size is order + 1)+ -> Vector a -- ^ the filter coefficients fir o be gn tn w = let mid = o `div` 2 (f,m) = unzip be- f' = diff (((fromIntegral gn) :: Double)/((fromIntegral tn) :: Double)/2.0) f+ f' = diff (((fromIntegral gn))/((fromIntegral tn))/2.0) f m' = interpolate f m f' grid = interpolate f' m' $ map (\x -> (fromIntegral x)/(fromIntegral gn)) [0..(gn-1)] grid' = map (\x -> x :+ 0) grid- (b,_) = fromComplex $ F.ifft $ fromList $ grid' ++ (reverse (drop 1 grid'))+ b = S.fromDouble $ fst $ fromComplex $ F.ifft $ double $ fromList $ grid' ++ (reverse (drop 1 grid')) b' = join [subVector ((dim b)-mid-1) (mid+1) b, subVector 1 (mid+1) b] in b' * w @@ -148,24 +154,24 @@ | x > 1.0 = 1.0 | otherwise = x -diff :: Double -> [Double] -> [Double]+diff :: S.Filterable a ⇒ a -> [a] -> [a] diff _ [] = [] diff _ [x] = [x] diff inc (x1:x2:xs) | x1 == x2 = (floor_zero $ x1-inc):x1:(ceil_one $ x1+inc):(diff inc (L.filter (/= x2) xs)) | otherwise = x1:(diff inc (x2:xs)) -interpolate :: [Double] -> [Double] -> [Double] -> [Double]+interpolate :: S.Filterable a ⇒ [a] -> [a] -> [a] -> [a] interpolate _ _ [] = [] interpolate x y (xp:xs) = if xp == 1.0 then ((interpolate'' ((length x)-1) x y xp):(interpolate x y xs)) else ((interpolate' x y xp):(interpolate x y xs)) -interpolate' :: [Double] -> [Double] -> Double -> Double+interpolate' :: S.Filterable a ⇒ [a] -> [a] -> a -> a interpolate' x y xp = let Just j = L.findIndex (> xp) x in (interpolate'' j x y xp) -interpolate'' :: Int -> [Double] -> [Double] -> Double -> Double+interpolate'' :: S.Filterable a ⇒ Int -> [a] -> [a] -> a -> a interpolate'' j x y xp = let x0 = x !! (j-1) y0 = y !! (j-1) x1 = x !! j@@ -175,19 +181,21 @@ ----------------------------------------------------------------------------- -- | determine the frequency response of a filter, given a vector of frequencies-freqzF :: Vector Double -- ^ zero coefficients- -> Vector Double -- ^ pole coefficients- -> Int -- ^ sampling rate - -> Vector Double -- ^ frequencies- -> Vector Double -- ^ frequency response+freqzF :: (S.Filterable a, Double ~ DoubleOf a, S.Filterable (DoubleOf a)) ⇒ + Vector a -- ^ zero coefficients+ -> Vector a -- ^ pole coefficients+ -> Int -- ^ sampling rate + -> Vector a -- ^ frequencies+ -> Vector a -- ^ frequency response freqzF b a s f = S.freqz b a ((2*pi/(fromIntegral s)) * f) -- | determine the frequency response of a filter, given a number of points and sampling rate-freqzN :: Vector Double -- ^ zero coefficients- -> Vector Double -- ^ pole coefficients- -> Int -- ^ sampling rate- -> Int -- ^ number of points- -> (Vector Double,Vector Double) -- ^ (frequencies,response)+freqzN :: (S.Filterable a, Enum a, Double ~ DoubleOf a) ⇒ + Vector a -- ^ zero coefficients+ -> Vector a -- ^ pole coefficients+ -> Int -- ^ sampling rate+ -> Int -- ^ number of points+ -> (Vector a,Vector a) -- ^ (frequencies,response) freqzN b a s n = let w' = linspace n (0,((fromIntegral n)-1)/(fromIntegral (2*n))) r = S.freqz b a ((2*pi)*w') in ((fromIntegral s)*w',r)@@ -199,12 +207,14 @@ analytic_signal = S.hilbert -- | the power (amplitude^2 = v * (conj c)) of an analytic signal-analytic_power :: Vector (Complex Double) -> Vector Double-analytic_power = S.complex_power+analytic_power :: S.Filterable a ⇒ Vector (Complex Double) -> Vector a+analytic_power = S.complex_power_ -- | the phase of an analytic signal-analytic_phase :: Vector (Complex Double) -> Vector Double-analytic_phase = uncurry arctan2 . fromComplex+analytic_phase :: (S.Filterable a, Container Vector a+ ,Double ~ DoubleOf a) ⇒ + Vector (Complex a) -> Vector a+analytic_phase = (uncurry arctan2) . fromComplex ----------------------------------------------------------------------------- @@ -226,25 +236,28 @@ ----------------------------------------------------------------------------- --- | take one sample from every n samples in the original-downsample :: Int -> Vector Double -> Vector Double-downsample = S.downsample-- -- | resize the vector to length n by resampling-resize :: Int -> Vector Double -> Vector Double-resize n v = downsample (dim v `div` n) v+resize :: S.Filterable a ⇒ Int -> Vector a -> Vector a+resize n v = S.downsample_ (dim v `div` n) v ----------------------------------------------------------------------------- --- | the difference between consecutive elements of a vector-deriv :: Vector Double -> Vector Double-deriv = S.deriv+-- | coefficients of a Hamming window+hamming :: S.Filterable a ⇒+ Int -- ^ length+ -> Vector a -- ^ the Hamming coeffficents+hamming = S.hamming_ ------------------------------------------------------------------------------+-- | resample, take one sample every n samples in the original+downsample :: S.Filterable a ⇒ Int -> Vector a -> Vector a+downsample = S.downsample_ +-- | the difference between consecutive elements of a vector+deriv :: S.Filterable a ⇒ Vector a -> Vector a+deriv = S.deriv_+ -- | unwrap the phase of signal (input expected to be within (-pi,pi)-unwrap :: Vector Double -> Vector Double-unwrap = S.unwrap+unwrap :: S.Filterable a ⇒ Vector a -> Vector a+unwrap = S.unwrap_ -----------------------------------------------------------------------------
lib/Numeric/Signal/Internal.hs view
@@ -1,4 +1,6 @@-{-# OPTIONS_GHC -fglasgow-exts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-} ----------------------------------------------------------------------------- -- | -- Module : Numeric.Signal.Internal@@ -15,15 +17,10 @@ module Numeric.Signal.Internal ( Convolvable(..),- hamming,- filter,+ Filterable(..), freqz, pwelch, hilbert,- complex_power,- downsample,- deriv,- unwrap ) where import Data.Packed.Development(createVector,vec,app1,app2,app3,app4)@@ -44,6 +41,7 @@ type PD = Ptr Double type PC = Ptr (Complex Double) +type PF = Ptr Float ----------------------------------------------------------------------------- @@ -53,6 +51,37 @@ ----------------------------------------------------------------------------- +class (Storable a, Container Vector a, Num (Vector a)+ , Convert a, Floating (Vector a), RealElement a+ , Num a)+ => Filterable a where+ -- | conver from Vector Double+ fromDouble :: Vector Double -> Vector a+-- b ~ ComplexOf a, Container Vector b, Convert b) => Filterable a where+ -- | filter a signal+ filter_ :: Vector a -- ^ zero coefficients+ -> Vector a -- ^ pole coefficients+ -> Vector a -- ^ input signal+ -> Vector a -- ^ output signal+ -- | coefficients of a Hamming window+ hamming_ :: Int -- ^ length+ -> Vector a -- ^ the Hamming coeffficents+ -- | the complex power : real $ v * (conj v)+ complex_power_ :: Vector (Complex Double) -- ^ input+ -> Vector a -- ^ output+ -- | resample, take one sample every n samples in the original+ downsample_ :: Int -> Vector a -> Vector a+ -- | the difference between consecutive elements of a vector+ deriv_ :: Vector a -> Vector a+ -- | unwrap the phase of signal (input expected to be within (-pi,pi)+ unwrap_ :: Vector a -> Vector a+ -- | evaluate a real coefficient polynomial for complex arguments+ polyEval_ :: Vector a -- ^ the real coefficients+ -> Vector (Complex Double) -- ^ the points at which to be evaluated+ -> Vector (Complex Double) -- ^ the values++-----------------------------------------------------------------------------+ instance Convolvable (Vector Double) where convolve x y = fst $ fromComplex $ F.ifft $ (F.fft (complex x) * F.fft (complex y)) -- convolve = convolve_vector_double@@ -64,6 +93,17 @@ foreign import ccall "signal-aux.h vector_double_convolve" signal_vector_double_convolve :: CInt -> PD -> CInt -> PD -> CInt -> PD -> IO CInt +instance Convolvable (Vector Float) where+ convolve x y = single $ fst $ fromComplex $ F.ifft $ (F.fft (complex $ double x) * F.fft (complex $ double y))+-- convolve = convolve_vector_double++convolve_vector_float c a = unsafePerformIO $ do+ r <- createVector (dim a)+ app3 signal_vector_float_convolve vec c vec a vec r "signalFloatConvolve"+ return r++foreign import ccall "signal-aux.h vector_float_convolve" signal_vector_float_convolve :: CInt -> PF -> CInt -> PF -> CInt -> PF -> IO CInt+ ----------------------------------------------------------------------------- instance Convolvable (Vector (Complex Double)) where@@ -79,18 +119,52 @@ ----------------------------------------------------------------------------- +instance Filterable Double where+ fromDouble = id+ filter_ = filterD+ hamming_ = hammingD+ complex_power_ = complex_powerD+ downsample_ = downsampleD+ deriv_ = derivD+ unwrap_ = unwrapD+ polyEval_ = polyEval++instance Filterable Float where+ fromDouble = single+ filter_ = filterF+ hamming_ = hammingF+ complex_power_ = complex_powerF+ downsample_ = downsampleF+ deriv_ = derivF+ unwrap_ = unwrapF+ polyEval_ c = polyEval (double c)++-----------------------------------------------------------------------------+ -- | filters the signal-filter :: Vector Double -- ^ zero coefficients+filterD :: Vector Double -- ^ zero coefficients -> Vector Double -- ^ pole coefficients -> Vector Double -- ^ input signal -> Vector Double -- ^ output signal-filter l k v = unsafePerformIO $ do+filterD l k v = unsafePerformIO $ do r <- createVector (dim v)- app4 signal_filter vec l vec k vec v vec r "signalFilter"+ app4 signal_filter_double vec l vec k vec v vec r "signalFilter" return r -foreign import ccall "signal-aux.h filter" signal_filter :: CInt -> PD -> CInt -> PD -> CInt -> PD -> CInt -> PD -> IO CInt+foreign import ccall "signal-aux.h filter_double" signal_filter_double :: CInt -> PD -> CInt -> PD -> CInt -> PD -> CInt -> PD -> IO CInt +-- | filters the signal+filterF :: Vector Float -- ^ zero coefficients+ -> Vector Float -- ^ pole coefficients+ -> Vector Float -- ^ input signal+ -> Vector Float -- ^ output signal+filterF l k v = unsafePerformIO $ do+ r <- createVector (dim v)+ app4 signal_filter_float vec l vec k vec v vec r "signalFilter"+ return r++foreign import ccall "signal-aux.h filter_float" signal_filter_float :: CInt -> PF -> CInt -> PF -> CInt -> PF -> CInt -> PF -> IO CInt+ ----------------------------------------------------------------------------- -- | Hilbert transform with original vector as real value, transformed as imaginary@@ -119,28 +193,51 @@ ----------------------------------------------------------------------------- -- | coefficients of a Hamming window-hamming :: Int -- ^ length+hammingD :: Int -- ^ length -> Vector Double -- ^ the Hamming coeffficents-hamming l +hammingD l | l == 1 = constant 1.0 1 | otherwise = unsafePerformIO $ do r <- createVector l- app1 signal_hamming vec r "Hamming"+ app1 signal_hamming_double vec r "Hamming" return r -foreign import ccall "signal-aux.h hamming" signal_hamming :: CInt -> PD -> IO CInt+foreign import ccall "signal-aux.h hamming_double" signal_hamming_double :: CInt -> PD -> IO CInt +-- | coefficients of a Hamming window+hammingF :: Int -- ^ length+ -> Vector Float -- ^ the Hamming coeffficents+hammingF l + | l == 1 = constant 1.0 1+ | otherwise = unsafePerformIO $ do+ r <- createVector l+ app1 signal_hamming_float vec r "Hamming"+ return r++foreign import ccall "signal-aux.h hamming_float" signal_hamming_float :: CInt -> PF -> IO CInt+ ----------------------------------------------------------------------------- -- | determine the frequency response of a filter-freqz :: Vector Double -- ^ zero coefficients- -> Vector Double -- ^ pole coefficients- -> Vector Double -- ^ points (between 0 and 2*pi)- -> Vector Double -- ^ response+{-freqz :: (Filterable a, Storable a, Container Vector a, Convert a, RealElement a,+ DoubleOf a ~ DoubleOf (RealOf b), RealElement c, c ~ DoubleOf a, c ~ DoubleOf (RealOf b),+ b ~ Complex a, b ~ ComplexOf a, Convert b, Container Vector b,+ Container Vector c, Convert c, b ~ ComplexOf a, b ~ ComplexOf c)+ ⇒ Vector a -- ^ zero coefficients+ -> Vector a -- ^ pole coefficients+ -> Vector a -- ^ points (between 0 and 2*pi)+ -> Vector a -- ^ response+-}+freqz :: (Filterable a, Complex Double ~ ComplexOf (DoubleOf a)+ ,Filterable (DoubleOf a)) => + Vector a -- ^ zero coefficients+ -> Vector a -- ^ pole coefficients+ -> Vector a -- ^ points (between 0 and 2*pi)+ -> Vector a -- ^ response freqz b a w = let k = max (dim b) (dim a)- hb = polyEval (postpad b k) (exp (scale (0 :+ 1) ((complex w) :: Vector (Complex Double))))- ha = polyEval (postpad a k) (exp (scale (0 :+ 1) ((complex w) :: Vector (Complex Double))))- in complex_power (hb / ha)+ hb = polyEval_ (postpad b k) (exp (scale (0 :+ 1) ((complex $ double w))))+ ha = polyEval_ (postpad a k) (exp (scale (0 :+ 1) ((complex $ double w))))+ in complex_power_ (hb / ha) postpad v n = let d = dim v in if d < n then join [v,(constant 0.0 (n-d))]@@ -162,47 +259,84 @@ ----------------------------------------------------------------------------- -- | the complex power : real $ v * (conj v)-complex_power :: Vector (Complex Double) -- ^ input+complex_powerD :: Vector (Complex Double) -- ^ input -> Vector Double -- ^ output-complex_power v = unsafePerformIO $ do+complex_powerD v = unsafePerformIO $ do r <- createVector (dim v)- app2 signal_complex_power vec v vec r "complex_power"+ app2 signal_complex_power_double vec v vec r "complex_power" return r -foreign import ccall "signal-aux.h complex_power" signal_complex_power :: CInt -> PC -> CInt -> PD -> IO CInt+foreign import ccall "signal-aux.h complex_power_double" signal_complex_power_double :: CInt -> PC -> CInt -> PD -> IO CInt +-- | the complex power : real $ v * (conj v)+complex_powerF :: Vector (Complex Double) -- ^ input+ -> Vector Float -- ^ output+complex_powerF v = unsafePerformIO $ do+ r <- createVector (dim v)+ app2 signal_complex_power_float vec v vec r "complex_power"+ return r++foreign import ccall "signal-aux.h complex_power_float" signal_complex_power_float :: CInt -> PC -> CInt -> PF -> IO CInt+ ----------------------------------------------------------------------------- -- | resample, take one sample every n samples in the original-downsample :: Int -> Vector Double -> Vector Double-downsample n v = unsafePerformIO $ do+downsampleD :: Int -> Vector Double -> Vector Double+downsampleD n v = unsafePerformIO $ do r <- createVector (dim v `div` n)- app2 (signal_downsample $ fromIntegral n) vec v vec r "downsample"+ app2 (signal_downsample_double $ fromIntegral n) vec v vec r "downsample" return r -foreign import ccall "signal-aux.h downsample" signal_downsample :: CInt -> CInt -> PD -> CInt -> PD -> IO CInt+foreign import ccall "signal-aux.h downsample_double" signal_downsample_double :: CInt -> CInt -> PD -> CInt -> PD -> IO CInt +-- | resample, take one sample every n samples in the original+downsampleF :: Int -> Vector Float -> Vector Float+downsampleF n v = unsafePerformIO $ do+ r <- createVector (dim v `div` n)+ app2 (signal_downsample_float $ fromIntegral n) vec v vec r "downsample"+ return r++foreign import ccall "signal-aux.h downsample_float" signal_downsample_float :: CInt -> CInt -> PF -> CInt -> PF -> IO CInt+ ----------------------------------------------------------------------------- -- | the difference between consecutive elements of a vector-deriv :: Vector Double -> Vector Double-deriv v = unsafePerformIO $ do+derivD :: Vector Double -> Vector Double+derivD v = unsafePerformIO $ do r <- createVector (dim v - 1)- app2 (signal_deriv) vec v vec r "diff"+ app2 (signal_deriv_double) vec v vec r "diff" return r -foreign import ccall "signal-aux.h vector_deriv" signal_deriv :: CInt -> PD -> CInt -> PD -> IO CInt+foreign import ccall "signal-aux.h vector_deriv_double" signal_deriv_double :: CInt -> PD -> CInt -> PD -> IO CInt +-- | the difference between consecutive elements of a vector+derivF :: Vector Float -> Vector Float+derivF v = unsafePerformIO $ do+ r <- createVector (dim v - 1)+ app2 (signal_deriv_float) vec v vec r "diff"+ return r++foreign import ccall "signal-aux.h vector_deriv_float" signal_deriv_float :: CInt -> PF -> CInt -> PF -> IO CInt+ ----------------------------------------------------------------------------- -- | unwrap the phase of signal (input expected to be within (-pi,pi)-unwrap :: Vector Double -> Vector Double-unwrap v = unsafePerformIO $ do+unwrapD :: Vector Double -> Vector Double+unwrapD v = unsafePerformIO $ do r <- createVector $ dim v- app2 signal_unwrap vec v vec r "unwrap"+ app2 signal_unwrap_double vec v vec r "unwrap" return r -foreign import ccall "signal-aux.h unwrap" signal_unwrap :: CInt -> PD -> CInt -> PD -> IO CInt+foreign import ccall "signal-aux.h unwrap_double" signal_unwrap_double :: CInt -> PD -> CInt -> PD -> IO CInt++-- | unwrap the phase of signal (input expected to be within (-pi,pi)+unwrapF :: Vector Float -> Vector Float+unwrapF v = unsafePerformIO $ do+ r <- createVector $ dim v+ app2 signal_unwrap_float vec v vec r "unwrap"+ return r++foreign import ccall "signal-aux.h unwrap_float" signal_unwrap_float :: CInt -> PF -> CInt -> PF -> IO CInt -----------------------------------------------------------------------------
lib/Numeric/Signal/Multichannel.hs view
@@ -235,7 +235,8 @@ -- | filter the data with the given passband-filter :: (Int,Int) -> Multichannel Double -> Multichannel Double+filter :: (S.Filterable a, Double ~ DoubleOf a, Container Vector (Complex a), Convert (Complex a)) ⇒ + (Int,Int) -> Multichannel a -> Multichannel a filter pb m = let m' = mapConcurrently (S.broadband_filter (_sampling_rate m) pb) m in m' { _filtered = Just pb } @@ -253,9 +254,10 @@ ----------------------------------------------------------------------------- -- | calculate the mutual information of the phase between pairs of channels (fills upper half of matrix)-mi_phase :: Multichannel Double -- ^ input data+mi_phase :: (S.Filterable a, Double ~ DoubleOf a) ⇒+ Multichannel a -- ^ input data -> Matrix Double-mi_phase m = let d = _data m+mi_phase m = let d = fmap double $ _data m histarray = mapArrayConcurrently (H.fromLimits 128 (-pi,pi)) d c = channels m pairs = I.array ((1,1),(c,c)) $ map (\(a,b) -> ((a,b),((a,b),d I.! a,d I.! b))) (range ((1,1),(c,c)))
lib/Numeric/Signal/signal-aux.c view
@@ -10,6 +10,23 @@ #include <stdio.h> +int vector_float_convolve(int cs, const float* c, int as, const float* a, int rs, float* r)+{+ int h = cs / 2;+ int li, ri;+ int i,j;++ for (i = 0; i < cs; i++) {+ li = i - h;+ ri = i + h;+ r[i] = 0;+ for (j = (li >= 0 ? li : 0); j < (ri < as ? ri : (as - 1)); j++) {+ r[i] += a[j]*c[j+h+1];+ }+ }+ return 0;+}+ int vector_double_convolve(int cs, const double* c, int as, const double* a, int rs, double* r) { int h = cs / 2;@@ -46,7 +63,7 @@ return 0; } -int filter(int ls, const double* l, int ks, const double* k, int vs, const double* v, int rs, double* r)+int filter_double(int ls, const double* l, int ks, const double* k, int vs, const double* v, int rs, double* r) { if (ls > vs || ks > vs) return 2000; // BAD_SIZE @@ -70,6 +87,30 @@ return 0; } +int filter_float(int ls, const float* l, int ks, const float* k, int vs, const float* v, int rs, float* r)+{+ if (ls > vs || ks > vs) return 2000; // BAD_SIZE++ int i,j;++ float L = l[0];+ float K = k[0];+ + int N = ls - 1;+ int M = ks - 1;++ for (i = 0; i < vs; i++) {+ r[i] = 0;+ for (j = 0; j < N; j++) {+ if (i - j > 0) r[i] -= (l[j+1])*v[i-j];+ }+ for (j = 0; j < M; j++) {+ if (i - j > 0) r[i] += (k[j+1])*r[i-j];+ }+ }+ return 0;+}+ int hilbert(int rs, gsl_complex* r) { int s = rs;@@ -148,7 +189,7 @@ return 0; } -int hamming(int rs, double* r)+int hamming_double(int rs, double* r) { int i; @@ -157,6 +198,15 @@ return 0; } +int hamming_float(int rs, float* r)+{+ int i;++ for (i = 0; i < rs; i++) r[i] = 0.54 - 0.46 * cos(2*M_PI*i/rs);++ return 0;+}+ int real_poly_complex_eval(int cs, const double* c, int zs, const gsl_complex* z, int rs, gsl_complex* r) { int i;@@ -167,7 +217,7 @@ return 0; } -int complex_power(int cs, const gsl_complex* c, int rs, double* r)+int complex_power_double(int cs, const gsl_complex* c, int rs, double* r) { if (rs != cs) return 2000; // BAD_SIZE @@ -179,7 +229,31 @@ return 0; } -int downsample(int n, int xs, const double* x, int rs, double* r)+int complex_power_float(int cs, const gsl_complex* c, int rs, float* r)+{+ if (rs != cs) return 2000; // BAD_SIZE++ int i;++ for (i = 0; i < cs; i++)+ r[i] = c[i].dat[0]*c[i].dat[0] + c[i].dat[1]*c[i].dat[1];++ return 0;+}++int downsample_double(int n, int xs, const double* x, int rs, double* r)+{+ if (rs != xs/n) return 2000; // BAD_SIZE+ + int i;++ for (i = 0; i < rs; i++)+ r[i] = x[i*n];++ return 0;+}++int downsample_float(int n, int xs, const float* x, int rs, float* r) { if (rs != xs/n) return 2000; // BAD_SIZE