cobot-0.1.1.7: src/Bio/Chain/Alignment/Type.hs
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE StandaloneDeriving #-}
module Bio.Chain.Alignment.Type where
import Bio.Chain (ChainLike (..))
import Control.DeepSeq (NFData (..))
import Control.Lens (Index, IxValue)
import Data.Array.Unboxed (Ix, UArray)
import Data.Kind (Type)
import GHC.Generics (Generic (..))
-- | Scoring function, returns substitution score for a couple of elements
--
-- type Scoring = Char -> Char -> Int
type Scoring a b = a -> b -> Int
-- | Simple gap penalty
--
type SimpleGap = Int
-- | Gap penalty with different 'SimpleGap' penalties for sequences.
--
-- First element of pair is penalty for first sequence passed to alignment
-- algorithm, second element — penalty for second passed sequence.
--
type SimpleGap2 = (SimpleGap, SimpleGap)
-- | Affine gap penalty
--
data AffineGap = AffineGap { gapOpen :: Int
, gapExtend :: Int
}
deriving (Show, Eq, Generic, NFData)
-- | Gap penalty with different 'AffineGap' penalties for sequences.
--
-- First element of pair is penalty for first sequence passed to alignment
-- algorithm, second element — penalty for second passed sequence.
--
type AffineGap2 = (AffineGap, AffineGap)
-- | Type class that describes possible gaps in alignments.
--
class IsGap a where
-- | Insertions are gaps in the first argument of an alignment function.
--
insertCostOpen :: a -> Int
insertCostExtend :: a -> Int
-- | Deletions are gaps in the second argument of an alignment function.
--
deleteCostOpen :: a -> Int
deleteCostExtend :: a -> Int
isAffine :: a -> Bool
isAffine x = insertCostOpen x /= insertCostExtend x || deleteCostOpen x /= deleteCostExtend x
instance IsGap SimpleGap where
insertCostOpen = id
insertCostExtend = id
deleteCostOpen = id
deleteCostExtend = id
instance IsGap SimpleGap2 where
insertCostOpen = fst
insertCostExtend = fst
deleteCostOpen = snd
deleteCostExtend = snd
instance IsGap AffineGap where
insertCostOpen = gapOpen
insertCostExtend = gapExtend
deleteCostOpen = gapOpen
deleteCostExtend = gapExtend
instance IsGap AffineGap2 where
insertCostOpen = gapOpen . fst
insertCostExtend = gapExtend . fst
deleteCostOpen = gapOpen . snd
deleteCostExtend = gapExtend . snd
-- | Edit operation could be insertion, deletion or match/mismatch
--
data EditOp = Insert | Delete | Match
deriving (Show, Eq, Ord, Bounded, Enum, Ix, Generic, NFData)
-- | Operation that was performed on current step of alignment
--
data Operation i j = INSERT { getJ :: j }
| DELETE { getI :: i }
| MATCH { getI :: i, getJ :: j }
deriving (Show, Eq, Ord, Generic, NFData)
isInsert, isDelete, isMatch :: Operation i j -> Bool
isInsert INSERT{} = True
isInsert _ = False
isDelete DELETE{} = True
isDelete _ = False
isMatch MATCH{} = True
isMatch _ = False
-- | Alignment matrix type
--
type Matrix m m' = UArray (Index m, Index m', EditOp) Int
-- | Traceback stop condition type
--
type Stop m m' = Matrix m m' -> m -> m' -> Index m -> Index m' -> Bool
-- | Traceback next move generator type
--
type Move m m'
= Matrix m m'
-> m -> m'
-> Index m -> Index m'
-> EditOp -- ^ Current matrix, used in affine alignment
-> (EditOp, Index m, Index m', Operation (Index m) (Index m'))
-- ^ Next matrix, next indices, new operation
-- | A set of traceback conditions
--
data Conditions m m' = Conditions { isStop :: Stop m m' -- ^ Should we stop?
, doMove :: Move m m' -- ^ Where to go next?
}
-- | Sequence Alignment result
--
data AlignmentResult m m' = AlignmentResult { score :: Int -- ^ Resulting score of alignment
, alignment :: [Operation (Index m) (Index m')] -- ^ Alignment structure
, sequence1 :: m -- ^ First chain
, sequence2 :: m' -- ^ Second chain
}
deriving (Generic)
instance (NFData a, NFData b) => NFData (UArray (a, b, EditOp) Int) where
rnf a = seq a ()
deriving instance (NFData a, NFData b, NFData (Index a), NFData (Index b))
=> NFData (AlignmentResult a b)
-- | Chain, that can be used for alignment
--
type Alignable m = (ChainLike m, Ix (Index m))
-- |Method of sequence alignment
--
class SequenceAlignment (a :: Type -> Type -> Type) where
-- | Defines wheater the alignment is semiglobal or not
--
semi :: a e1 e2 -> Bool
{-# INLINABLE semi #-}
semi = const False
-- | Traceback conditions of alignment
--
cond :: (Alignable m, Alignable m') => a (IxValue m) (IxValue m') -> Conditions m m'
-- | Starting position in matrix for traceback procedure
--
traceStart :: (Alignable m, Alignable m') => a (IxValue m) (IxValue m') -> Matrix m m' -> m -> m' -> (Index m, Index m')
-- | Distance matrix element
--
scoreMatrix :: (Alignable m, Alignable m') => a (IxValue m) (IxValue m') -> m -> m' -> Matrix m m'