bioinformatics-toolkit 0.7.0 → 0.8.0
raw patch · 6 files changed
+115/−102 lines, 6 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Bio.Data.Bed.Utils: getMotifPValue :: Monad m => Maybe Double -> [Motif] -> Bkgd -> ConduitT BED BED m ()
- Bio.Data.Bed.Utils: getMotifScore :: MonadIO m => Genome -> [Motif] -> Bkgd -> ConduitT BED BED m ()
- Bio.Data.Bed.Utils: motifScan :: (BEDLike b, MonadIO m) => Genome -> [Motif] -> Bkgd -> Double -> ConduitT b BED m ()
- Bio.Motif.Search: SpaceDistribution :: Motif -> (Int, Int) -> Motif -> (Int, Int) -> [(Int, Int)] -> [(Int, Int)] -> SpaceDistribution
- Bio.Motif.Search: [_motif1] :: SpaceDistribution -> Motif
- Bio.Motif.Search: [_motif2] :: SpaceDistribution -> Motif
- Bio.Motif.Search: [_nSites1] :: SpaceDistribution -> (Int, Int)
- Bio.Motif.Search: [_nSites2] :: SpaceDistribution -> (Int, Int)
- Bio.Motif.Search: [_opposite] :: SpaceDistribution -> [(Int, Int)]
- Bio.Motif.Search: [_same] :: SpaceDistribution -> [(Int, Int)]
- Bio.Motif.Search: data SpaceDistribution
- Bio.Motif.Search: findTFBS' :: Bkgd -> PWM -> DNA a -> Double -> Bool -> [Int]
- Bio.Motif.Search: instance GHC.Read.Read Bio.Motif.Search.SpaceDistribution
- Bio.Motif.Search: instance GHC.Show.Show Bio.Motif.Search.SpaceDistribution
- Bio.Motif.Search: spaceConstraint :: [(Motif, Motif)] -> Bkgd -> Double -> Int -> Int -> DNA a -> [SpaceDistribution]
- Bio.Motif.Search: spaceConstraintHelper :: (Vector Int, Vector Int) -> (Vector Int, Vector Int) -> Int -> Int -> ([(Int, Int)], [(Int, Int)])
- Bio.RealWorld.Reactome: instance Data.Aeson.Types.FromJSON.FromJSON Bio.RealWorld.Reactome.Obj
- Bio.RealWorld.Reactome: instance Data.Aeson.Types.ToJSON.ToJSON Bio.RealWorld.Reactome.Obj
+ Bio.Data.Bed.Utils: CutoffMotif :: ByteString -> PWM -> Vector Double -> PWM -> Vector Double -> Bkgd -> Double -> CDF -> CutoffMotif
+ Bio.Data.Bed.Utils: [_background] :: CutoffMotif -> Bkgd
+ Bio.Data.Bed.Utils: [_cdf] :: CutoffMotif -> CDF
+ Bio.Data.Bed.Utils: [_cutoff] :: CutoffMotif -> Double
+ Bio.Data.Bed.Utils: [_motif_name] :: CutoffMotif -> ByteString
+ Bio.Data.Bed.Utils: [_motif_pwm] :: CutoffMotif -> PWM
+ Bio.Data.Bed.Utils: [_motif_pwm_rc] :: CutoffMotif -> PWM
+ Bio.Data.Bed.Utils: [_motif_sigma] :: CutoffMotif -> Vector Double
+ Bio.Data.Bed.Utils: [_motif_sigma_rc] :: CutoffMotif -> Vector Double
+ Bio.Data.Bed.Utils: data CutoffMotif
+ Bio.Data.Bed.Utils: mkCutoffMotif :: Bkgd -> Double -> Motif -> CutoffMotif
+ Bio.Data.Bed.Utils: scanMotif :: (BEDLike b, MonadIO m) => Genome -> [CutoffMotif] -> ConduitT b BED m ()
+ Bio.Motif.Search: findTFBSWith :: Monad m => Vector Double -> Bkgd -> PWM -> DNA a -> Double -> Bool -> ConduitT i (Int, Double) m ()
+ Bio.Motif.Search: optimalScoresSuffix :: Bkgd -> PWM -> Vector Double
+ Bio.RealWorld.Reactome: instance Data.Aeson.Types.Class.FromJSON Bio.RealWorld.Reactome.Obj
+ Bio.RealWorld.Reactome: instance Data.Aeson.Types.Class.ToJSON Bio.RealWorld.Reactome.Obj
- Bio.Data.Bed: _bed :: forall bed_aCm4 a_aCm5 bed_aCxi. Lens (BEDExt bed_aCm4 a_aCm5) (BEDExt bed_aCxi a_aCm5) bed_aCm4 bed_aCxi
+ Bio.Data.Bed: _bed :: forall bed_aB9T a_aB9U bed_aBld. Lens (BEDExt bed_aB9T a_aB9U) (BEDExt bed_aBld a_aB9U) bed_aB9T bed_aBld
- Bio.Data.Bed: _data :: forall bed_aCm4 a_aCm5 a_aCxj. Lens (BEDExt bed_aCm4 a_aCm5) (BEDExt bed_aCm4 a_aCxj) a_aCm5 a_aCxj
+ Bio.Data.Bed: _data :: forall bed_aB9T a_aB9U a_aBle. Lens (BEDExt bed_aB9T a_aB9U) (BEDExt bed_aB9T a_aBle) a_aB9U a_aBle
- Bio.Data.Bed: score :: BEDLike b => Lens' b (Maybe Double)
+ Bio.Data.Bed: score :: BEDLike b => Lens' b (Maybe Int)
- Bio.Data.Bed.Types: BED :: !ByteString -> !Int -> !Int -> !Maybe ByteString -> !Maybe Double -> !Maybe Bool -> BED
+ Bio.Data.Bed.Types: BED :: !ByteString -> !Int -> !Int -> !Maybe ByteString -> !Maybe Int -> !Maybe Bool -> BED
- Bio.Data.Bed.Types: BroadPeak :: !ByteString -> !Int -> !Int -> !Maybe ByteString -> !Double -> !Maybe Bool -> !Double -> !Maybe Double -> !Maybe Double -> BroadPeak
+ Bio.Data.Bed.Types: BroadPeak :: !ByteString -> !Int -> !Int -> !Maybe ByteString -> !Int -> !Maybe Bool -> !Double -> !Maybe Double -> !Maybe Double -> BroadPeak
- Bio.Data.Bed.Types: NarrowPeak :: !ByteString -> !Int -> !Int -> !Maybe ByteString -> !Double -> !Maybe Bool -> !Double -> !Maybe Double -> !Maybe Double -> !Maybe Int -> NarrowPeak
+ Bio.Data.Bed.Types: NarrowPeak :: !ByteString -> !Int -> !Int -> !Maybe ByteString -> !Int -> !Maybe Bool -> !Double -> !Maybe Double -> !Maybe Double -> !Maybe Int -> NarrowPeak
- Bio.Data.Bed.Types: [_bed_score] :: BED -> !Maybe Double
+ Bio.Data.Bed.Types: [_bed_score] :: BED -> !Maybe Int
- Bio.Data.Bed.Types: [_bpScore] :: BroadPeak -> !Double
+ Bio.Data.Bed.Types: [_bpScore] :: BroadPeak -> !Int
- Bio.Data.Bed.Types: [_npScore] :: NarrowPeak -> !Double
+ Bio.Data.Bed.Types: [_npScore] :: NarrowPeak -> !Int
- Bio.Data.Bed.Types: _bed :: forall bed_aCm4 a_aCm5 bed_aCxi. Lens (BEDExt bed_aCm4 a_aCm5) (BEDExt bed_aCxi a_aCm5) bed_aCm4 bed_aCxi
+ Bio.Data.Bed.Types: _bed :: forall bed_aB9T a_aB9U bed_aBld. Lens (BEDExt bed_aB9T a_aB9U) (BEDExt bed_aBld a_aB9U) bed_aB9T bed_aBld
- Bio.Data.Bed.Types: _data :: forall bed_aCm4 a_aCm5 a_aCxj. Lens (BEDExt bed_aCm4 a_aCm5) (BEDExt bed_aCm4 a_aCxj) a_aCm5 a_aCxj
+ Bio.Data.Bed.Types: _data :: forall bed_aB9T a_aB9U a_aBle. Lens (BEDExt bed_aB9T a_aB9U) (BEDExt bed_aB9T a_aBle) a_aB9U a_aBle
- Bio.Data.Bed.Types: score :: BEDLike b => Lens' b (Maybe Double)
+ Bio.Data.Bed.Types: score :: BEDLike b => Lens' b (Maybe Int)
- Bio.Motif.Search: findTFBS :: Monad m => Bkgd -> PWM -> DNA a -> Double -> Bool -> ConduitT i Int m ()
+ Bio.Motif.Search: findTFBS :: Monad m => Bkgd -> PWM -> DNA a -> Double -> Bool -> ConduitT i (Int, Double) m ()
- Bio.Motif.Search: findTFBSSlow :: Monad m => Bkgd -> PWM -> DNA a -> Double -> ConduitT i Int m ()
+ Bio.Motif.Search: findTFBSSlow :: Monad m => Bkgd -> PWM -> DNA a -> Double -> ConduitT i (Int, Double) m ()
Files
- bioinformatics-toolkit.cabal +1/−1
- src/Bio/Data/Bed/Types.hs +15/−12
- src/Bio/Data/Bed/Utils.hs +50/−65
- src/Bio/Motif.hs +12/−9
- src/Bio/Motif/Search.hs +27/−15
- tests/Tests/Motif.hs +10/−0
bioinformatics-toolkit.cabal view
@@ -1,5 +1,5 @@ name: bioinformatics-toolkit-version: 0.7.0+version: 0.8.0 synopsis: A collection of bioinformatics tools description: A collection of bioinformatics tools license: MIT
src/Bio/Data/Bed/Types.hs view
@@ -56,7 +56,7 @@ chromStart :: Lens' b Int chromEnd :: Lens' b Int name :: Lens' b (Maybe B.ByteString)- score :: Lens' b (Maybe Double)+ score :: Lens' b (Maybe Int) strand :: Lens' b (Maybe Bool) -- | Return the size of a bed region.@@ -90,7 +90,7 @@ , _bed_chromStart :: !Int , _bed_chromEnd :: !Int , _bed_name :: !(Maybe B.ByteString)- , _bed_score :: !(Maybe Double)+ , _bed_score :: !(Maybe Int) , _bed_strand :: !(Maybe Bool) -- ^ True: "+", False: "-" } deriving (Eq, Show, Read) @@ -122,21 +122,24 @@ getName x | x == "." = Nothing | otherwise = Just x getScore x | x == "." = Nothing- | otherwise = Just . readDouble $ x+ | s >= 0 && s <= 1000 = Just s+ | otherwise = error "score must be in [0, 1000]."+ where+ s = readInt x getStrand str | str == "-" = Just False | str == "+" = Just True | otherwise = Nothing {-# INLINE fromLine #-} toLine (BED f1 f2 f3 f4 f5 f6) = B.intercalate "\t"- [ f1, (B.pack.show) f2, (B.pack.show) f3, fromMaybe "." f4, score'- , strand' ]+ [ f1, fromJust $ packDecimal f2, fromJust $ packDecimal f3+ , fromMaybe "." f4, score', strand' ] where strand' | f6 == Just True = "+" | f6 == Just False = "-" | otherwise = "." score' = case f5 of- Just x -> toShortest x+ Just x -> fromJust $ packDecimal x _ -> "." {-# INLINE toLine #-} @@ -180,7 +183,7 @@ , _npStart :: !Int , _npEnd :: !Int , _npName :: !(Maybe B.ByteString)- , _npScore :: !Double+ , _npScore :: !Int , _npStrand :: !(Maybe Bool) , _npSignal :: !Double , _npPvalue :: !(Maybe Double)@@ -207,7 +210,7 @@ fromLine l = NarrowPeak a (readInt b) (readInt c) (if d == "." then Nothing else Just d)- (readDouble e)+ (readInt e) (if f == "." then Nothing else if f == "+" then Just True else Just False) (readDouble g) (readDoubleNonnegative h)@@ -219,7 +222,7 @@ toLine (NarrowPeak a b c d e f g h i j) = B.intercalate "\t" [ a, fromJust $ packDecimal b, fromJust $ packDecimal c, fromMaybe "." d- , toShortest e+ , fromJust $ packDecimal e , case f of Nothing -> "." Just True -> "+"@@ -239,7 +242,7 @@ , _bpStart :: !Int , _bpEnd :: !Int , _bpName :: !(Maybe B.ByteString)- , _bpScore :: !Double+ , _bpScore :: !Int , _bpStrand :: !(Maybe Bool) , _bpSignal :: !Double , _bpPvalue :: !(Maybe Double)@@ -264,7 +267,7 @@ fromLine l = BroadPeak a (readInt b) (readInt c) (if d == "." then Nothing else Just d)- (readDouble e)+ (readInt e) (if f == "." then Nothing else if f == "+" then Just True else Just False) (readDouble g) (readDoubleNonnegative h)@@ -275,7 +278,7 @@ toLine (BroadPeak a b c d e f g h i) = B.intercalate "\t" [ a, fromJust $ packDecimal b, fromJust $ packDecimal c, fromMaybe "." d- , toShortest e+ , fromJust $ packDecimal e , case f of Nothing -> "." Just True -> "+"
src/Bio/Data/Bed/Utils.hs view
@@ -1,14 +1,15 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE LambdaCase #-}+{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE BangPatterns #-} module Bio.Data.Bed.Utils ( fetchSeq , fetchSeq'- , motifScan- , getMotifScore- , getMotifPValue+ , CutoffMotif(..)+ , mkCutoffMotif+ , scanMotif , monoColonalize , BaseMap(..) , baseMap@@ -39,7 +40,7 @@ import Bio.Data.Bed import Bio.Data.Bed.Types-import Bio.Motif (Bkgd (..), Motif (..))+import Bio.Motif (Bkgd (..), Motif (..), CDF, PWM) import qualified Bio.Motif as Motif import qualified Bio.Motif.Search as Motif import Bio.Seq hiding (length)@@ -64,71 +65,55 @@ fetchSeq' g beds = runConduit $ yieldMany beds .| fetchSeq g .| sinkList {-# INLINE fetchSeq' #-} --- | Identify motif binding sites-motifScan :: (BEDLike b, MonadIO m)- => Genome -> [Motif] -> Bkgd -> Double -> ConduitT b BED m ()-motifScan g motifs bg p = awaitForever $ \bed -> do- r <- liftIO $ getSeq g (bed^.chrom, bed^.chromStart, bed^.chromEnd)- case r of- Left _ -> liftIO $ hPutStrLn stderr $- "Warning: no sequence for region: " ++ show - (bed^.chrom, bed^.chromStart, bed^.chromEnd)- Right dna -> mapM_ (getTFBS dna (bed^.chrom, bed^.chromStart)) motifs'- where- getTFBS dna (chr, s) (nm, (pwm, cutoff), (pwm', cutoff')) = toProducer- ( (Motif.findTFBS bg pwm (dna :: DNA IUPAC) cutoff True .|- mapC (\i -> bed & chromStart +~ i & chromEnd +~ i & strand .~ Just True)) >>- (Motif.findTFBS bg pwm' dna cutoff' True .|- mapC (\i -> bed & chromStart +~ i & chromEnd +~ i & strand .~ Just False)) )- where- n = Motif.size pwm- bed = asBed chr s (s+n) & name .~ Just nm- motifs' = flip map motifs $ \(Motif nm pwm) ->- let cutoff = Motif.pValueToScore p bg pwm- cutoff' = Motif.pValueToScore p bg pwm'- pwm' = Motif.rcPWM pwm- in (nm, (pwm, cutoff), (pwm', cutoff'))-{-# INLINE motifScan #-}+-- | Motif with predefined cutoff score. All necessary intermediate data+-- structure for motif scanning are stored.+data CutoffMotif = CutoffMotif+ { _motif_name :: B.ByteString+ , _motif_pwm :: PWM+ , _motif_sigma :: U.Vector Double+ , _motif_pwm_rc :: PWM+ , _motif_sigma_rc :: U.Vector Double+ , _background :: Bkgd+ , _cutoff :: Double+ , _cdf :: CDF } --- | Retrieve motif matching scores-getMotifScore :: MonadIO m- => Genome -> [Motif] -> Bkgd -> ConduitT BED BED m ()-getMotifScore g motifs bg = awaitForever $ \bed -> do- r <- liftIO $ getSeq g (bed^.chrom, bed^.chromStart, bed^.chromEnd)- let r' = case bed^.strand of- Just False -> rc <$> r- _ -> r- case r' of- Left _ -> return ()- Right dna -> do- let pwm = M.lookupDefault (error "can't find motif with given name")- (fromJust $ bed^.name) motifMap- sc = Motif.score bg pwm (dna :: DNA IUPAC)- yield $ score .~ Just sc $ bed+mkCutoffMotif :: Bkgd+ -> Double -- ^ p-value+ -> Motif -> CutoffMotif+mkCutoffMotif bg p motif = CutoffMotif (_name motif) (_pwm motif) sigma pwm'+ sigma' bg sc $ Motif.truncateCDF (1 - p * 10) cdf where- motifMap = M.fromListWith (error "found motif with same name") $- map (\(Motif nm pwm) -> (nm, pwm)) motifs-{-# INLINE getMotifScore #-}+ cdf = Motif.scoreCDF bg $ _pwm motif+ sc = Motif.cdf' cdf $ 1 - p+ sigma = Motif.optimalScoresSuffix bg $ _pwm motif+ pwm' = Motif.rcPWM $ _pwm motif+ sigma' = Motif.optimalScoresSuffix bg pwm' -getMotifPValue :: Monad m- => Maybe Double -- ^ whether to truncate the motif score CDF.- -- Doing this will significantly reduce memory- -- usage without sacrifice accuracy.- -> [Motif] -> Bkgd -> ConduitT BED BED m ()-getMotifPValue truncation motifs bg = mapC $ \bed ->- let nm = fromJust $ bed^.name- sc = fromJust $ bed^.score- d = M.lookupDefault (error "can't find motif with given name")- nm motifMap- p = 1 - Motif.cdf d sc- in score .~ Just p $ bed+-- | Motif score is in [0, 1000]: ( 1 / (1 + exp (-(-logP - 5))) ) * 1000.+scanMotif :: (BEDLike b, MonadIO m)+ => Genome -> [CutoffMotif] -> ConduitT b BED m ()+scanMotif g motifs = awaitForever $ \bed -> do+ let (chr, start, end) = (bed^.chrom, bed^.chromStart, bed^.chromEnd)+ liftIO (getSeq g (chr, start, end)) >>= \case+ Left _ -> liftIO $ hPutStrLn stderr $+ "Warning: no sequence for region: " ++ show (chr, start, end)+ Right dna -> forM_ motifs $ \CutoffMotif{..} -> do+ let mkBed str (i, sc) = BED chr (start + i) (start + i + n)+ (Just $ _motif_name) (Just $ toAffinity $ 1 - Motif.cdf _cdf sc)+ (Just str)+ n = Motif.size _motif_pwm+ -- Scan forward strand+ Motif.findTFBSWith _motif_sigma _background _motif_pwm+ (dna :: DNA IUPAC) _cutoff True .| mapC (mkBed True)+ -- Scan reverse strand+ Motif.findTFBSWith _motif_sigma_rc _background _motif_pwm_rc+ dna _cutoff True .| mapC (mkBed False) where- motifMap = M.fromListWith (error "getMotifPValue: found motif with same name") $- map (\(Motif nm pwm) -> (nm, compressCDF $ Motif.scoreCDF bg pwm)) motifs- compressCDF = case truncation of- Nothing -> id- Just x -> Motif.truncateCDF x-{-# INLINE getMotifPValue #-}+ toAffinity x' = round $ sc * 1000+ where+ sc = 1 / (1 + exp (-(x - 5)))+ x = negate $ logBase 10 $ max 1e-20 x'+{-# INLINE scanMotif #-} -- | process a sorted BED stream, keep only mono-colonal tags monoColonalize :: Monad m => ConduitT BED BED m ()
src/Bio/Motif.hs view
@@ -252,15 +252,18 @@ cdf' :: CDF -> Double -> Double cdf' (CDF v) p | p > 1 || p < 0 = error "p must be in [0,1]"- | otherwise = let i = binarySearchBy cmp v p- in case () of- _ | i >= n -> 1/0- | i == 0 -> if p == snd (U.head v) then fst (U.head v) else undefined- | otherwise -> let (a, a') = v U.! (i-1)- (b, b') = v U.! i- α = (b' - p) / (b' - a')- β = (p - a') / (b' - a')- in α * a + β * b+ | otherwise =+ let i = binarySearchBy cmp v p+ in case () of+ _ | i >= n -> 1/0+ | i == 0 -> if p == snd (U.head v)+ then fst (U.head v)+ else error "cdf': impossible!"+ | otherwise -> let (a, a') = v U.! (i-1)+ (b, b') = v U.! i+ α = (b' - p) / (b' - a')+ β = (p - a') / (b' - a')+ in α * a + β * b where cmp (_,a) = compare a n = U.length v
src/Bio/Motif/Search.hs view
@@ -3,12 +3,10 @@ module Bio.Motif.Search ( findTFBS- , findTFBS'+ , findTFBSWith , findTFBSSlow , maxMatchSc- , SpaceDistribution(..)- , spaceConstraint- , spaceConstraintHelper+ , optimalScoresSuffix ) where import Conduit@@ -40,21 +38,35 @@ -> Double -> Bool -- ^ whether to skip ambiguous sequences. Recommend: True -- in most cases- -> ConduitT i Int m ()-findTFBS bg pwm dna thres skip = loop 0+ -> ConduitT i (Int, Double) m ()+findTFBS bg pwm dna thres skip = findTFBSWith sigma bg pwm dna thres skip where+ sigma = optimalScoresSuffix bg pwm+{-# INLINE findTFBS #-}++findTFBSWith :: Monad m+ => U.Vector Double -- ^ best possible match score of suffixes+ -> Bkgd+ -> PWM+ -> DNA a+ -> Double+ -> Bool -- ^ whether to skip ambiguous sequences. Recommend: True+ -- in most cases+ -> ConduitT i (Int, Double) m ()+findTFBSWith sigma bg pwm dna thres skip = loop 0+ where loop !i | i >= l - n + 1 = return ()- | otherwise = do let (d, _) = searchFn bg pwm sigma dna i thres+ | otherwise = do let (d, sc) = searchFn bg pwm sigma dna i thres if d == n - 1- then yield i >> loop (i+1)+ then yield (i, sc) >> loop (i+1) else loop (i+1)- sigma = optimalScoresSuffix bg pwm l = Seq.length dna n = size pwm searchFn | skip = lookAheadSearch' | otherwise = lookAheadSearch-{-# INLINE findTFBS #-}+{-# INLINE findTFBSWith #-} +{- -- | a parallel version of findTFBS findTFBS' :: Bkgd -> PWM@@ -78,14 +90,15 @@ searchFn | skip = lookAheadSearch' | otherwise = lookAheadSearch {-# INLINE findTFBS' #-}+-} -- | use naive search-findTFBSSlow :: Monad m => Bkgd -> PWM -> DNA a -> Double -> ConduitT i Int m ()+findTFBSSlow :: Monad m => Bkgd -> PWM -> DNA a -> Double -> ConduitT i (Int, Double) m () findTFBSSlow bg pwm dna thres = scores' bg pwm dna .| loop 0 where loop i = do v <- await case v of- Just v' -> if v' >= thres then yield i >> loop (i+1)+ Just v' -> if v' >= thres then yield (i, v') >> loop (i+1) else loop (i+1) _ -> return () {-# INLINE findTFBSSlow #-}@@ -193,6 +206,7 @@ n = size pwm {-# INLINE lookAheadSearch' #-} +{- data SpaceDistribution = SpaceDistribution { _motif1 :: Motif , _nSites1 :: (Int, Int)@@ -254,15 +268,13 @@ nRF = map (nOverlap rv1 fw2' w) $ reverse rs {-# INLINE spaceConstraintHelper #-} -{- computePValue :: Double -> [Int] -> [(Int, Double)] computePValue p xs = zip xs $ map (pValue n p) xs where n = foldl' (+) 0 xs-{-# INLINE computePValue #-} pValue :: Int -> Double -> Int -> Double pValue n p x | n > 2000 = complCumulative (poisson (fromIntegral n* p)) $ fromIntegral x | otherwise = complCumulative (binomial n p) $ fromIntegral x-{-# INLINE pValue #-}+ -}
tests/Tests/Motif.hs view
@@ -43,6 +43,7 @@ , testCase "Max matching score" maxScTest , testCase "pValue calculation" pValueTest , testCase "CDF truncate test" cdfTruncateTest+ , testCase "Reverse Complentary" reverseComplentary ] @@ -86,3 +87,12 @@ assertEqual "CDF truncate" expect actual where pValueToScore' p bg pwm = cdf' (truncateCDF 0.999 $ scoreCDF bg pwm) $ 1 - p++reverseComplentary :: Assertion+reverseComplentary = do+ ms <- motifs+ let expect = map (\x -> map approx $ scores def (_pwm x) dna) ms+ actual = map (\x -> map approx $ reverse $ scores def (rcPWM $ _pwm x) $ rc dna) ms+ assertEqual "reverse complentary" expect actual+ where+ approx x = round $ 100000 * x