{-# LANGUAGE ViewPatterns #-}
module Bio.Sequence.Functions.Weight
( mean
, meanInRange
, getWeight
, unsafeGetWeight
, getWeights
, toWeighted
, unsafeToWeighted
) where
import Bio.Sequence.Class (ContainsWeight,
IsBareSequence,
IsSequence (..),
IsWeight (..),
IsWeightedSequence, sequ,
unsafeWeightedSequence,
weightedSequence, weights)
import Bio.Sequence.Functions.Sequence (length)
import Bio.Sequence.Utilities (unsafeEither)
import Control.Lens
import Control.Monad.Except (MonadError, throwError)
import Data.Text (Text)
import Data.Vector (Vector)
import qualified Data.Vector as V (drop, length, take,
toList, (!))
import Prelude hiding (drop, head, length,
null, reverse, tail, take,
(!!))
type RangeInclusive = (Int, Int)
mean :: ContainsWeight s => s -> Double
mean s = meanInRange s (0, length s - 1)
meanInRange :: ContainsWeight s => s -> RangeInclusive -> Double
meanInRange (toSequence -> s) (lInd, rInd) = res
where
neededWeights = V.take (rInd + 1) $ V.drop lInd $ s ^. weights
res = mean' $ fmap toDouble neededWeights
mean' :: Vector Double -> Double
mean' l = sum l / fromIntegral (V.length l)
getWeight :: (ContainsWeight s, MonadError Text m) => s -> Int -> m (Weight s)
getWeight (toSequence -> s) i | i >= V.length ws = throwError indexError
| otherwise = pure $ ws V.! i
where
ws = s ^. weights
indexError :: Text
indexError = "Bio.Sequence.Functions.Weight: index out of range."
unsafeGetWeight :: ContainsWeight s => s -> Int -> Weight s
unsafeGetWeight sequ' = unsafeEither . getWeight sequ'
getWeights :: ContainsWeight s => s -> [Weight s]
getWeights = V.toList . (^. weights) . toSequence
toWeighted :: (IsBareSequence s, IsWeightedSequence s', Weight s' ~ w, Element s ~ Element s', MonadError Text m) => s -> [w] -> m s'
toWeighted (toSequence -> s) = weightedSequence (V.toList $ s ^. sequ)
unsafeToWeighted :: (IsBareSequence s, IsWeightedSequence s', Weight s' ~ w, Element s ~ Element s') => s -> [w] -> s'
unsafeToWeighted (toSequence -> s) = unsafeWeightedSequence (V.toList $ s ^. sequ)