packages feed

bio-sequence (empty) → 0.1.0.0

raw patch · 23 files changed

+851/−0 lines, 23 filesdep +QuickCheckdep +arraydep +basesetup-changed

Dependencies added: QuickCheck, array, base, bio-sequence, bytestring, hspec, parsec, template-haskell, text

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Biocad (c) 2017++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Bogdan Neterebskii nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,2 @@+# sequence+TODO
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ bio-sequence.cabal view
@@ -0,0 +1,70 @@+name:                bio-sequence+version:             0.1.0.0+synopsis:            Initial project template from stack+description:         Please see README.md+homepage:            https://github.com/biocad/bio-sequence+license:             BSD3+license-file:        LICENSE+author:              Pavel Yakovlev+maintainer:          yakovlev@biocad.ru+copyright:           Copyright: (c) 2017 Biocad+category:            Bio+build-type:          Simple+extra-source-files:  README.md+cabal-version:       >=1.10++library+  hs-source-dirs:      src+  exposed-modules:     Bio.Sequence+                     , Bio.Sequence.Alignment+                     , Bio.Sequence.Alignment.Matrix+                     , Bio.Sequence.Alignment.Scoring+                     , Bio.Sequence.AminoAcid+                     , Bio.Sequence.Parser.Fasta+                     , Bio.Macro+  other-modules:       Bio.Sequence.Alignment.Internal.Type+                     , Bio.Sequence.Alignment.Internal.Instances+                     , Bio.Sequence.Alignment.Internal.Matrix.Scoring+                     , Bio.Sequence.Alignment.Internal.Matrix.Template+                     , Bio.Sequence.Alignment.Scoring.Similarity+                     , Bio.Sequence.AminoAcid.Internal.Types+                     , Bio.Sequence.Parser.Fasta.Internal.Parser+                     , Bio.Sequence.Parser.Fasta.Internal.Converters+                     , Bio.Macro.Internal.Instances+                     , Bio.Macro.Internal.Types+  build-depends:       base >= 4.7 && < 5+                     , bytestring+                     , array+                     , template-haskell+                     , text+                     , parsec+  ghc-options:         -Wall -O2+  default-language:    Haskell2010++test-suite sequence-test+  type:                exitcode-stdio-1.0+  hs-source-dirs:      test+  main-is:             Spec.hs+  build-depends:       base+                     , bio-sequence+                     , bytestring+                     , hspec+                     , QuickCheck+  ghc-options:         -threaded -rtsopts -with-rtsopts=-N+  default-language:    Haskell2010++test-suite similarity+  type:                exitcode-stdio-1.0+  hs-source-dirs:      test+  main-is:             SpecSimilarity.hs+  build-depends:       base+                     , bio-sequence+                     , bytestring+                     , hspec+                     , QuickCheck+  ghc-options:         -threaded -rtsopts -with-rtsopts=-N+  default-language:    Haskell2010++source-repository head+  type:     git+  location: https://github.com/biocad/bio-sequence
+ src/Bio/Macro.hs view
@@ -0,0 +1,7 @@+module Bio.Macro+  ( MacroMolecule (..), Chain (..)++  ) where++import           Bio.Macro.Internal.Instances ()+import           Bio.Macro.Internal.Types     (Chain (..), MacroMolecule (..))
+ src/Bio/Macro/Internal/Instances.hs view
@@ -0,0 +1,14 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}++module Bio.Macro.Internal.Instances+  (++  ) where++import           Bio.Macro.Internal.Types (Chain (..), MacroMolecule (..))++instance Functor (MacroMolecule a) where+  fmap f mm = mm { mmChains = (f <$>) <$> mmChains mm }++instance Functor (Chain t) where+  fmap f ch = ch { chainResidues = f <$> chainResidues ch }
+ src/Bio/Macro/Internal/Types.hs view
@@ -0,0 +1,15 @@+module Bio.Macro.Internal.Types+  ( MacroMolecule (..)+  , Chain (..)++  ) where++data MacroMolecule a r = MacroMolecule { mmName   :: !String+                                       , mmChains :: ![Chain a r]+                                       }+  deriving (Show, Eq)++data Chain t r = Chain { chainType     :: !t+                       , chainResidues :: ![r]+                       }+  deriving (Show, Eq)
+ src/Bio/Sequence.hs view
@@ -0,0 +1,9 @@+module Bio.Sequence+  ( Sequence+  , Chain (..)+  ) where++import           Bio.Macro (Chain (..))+import           Data.Text (Text)++type Sequence = Chain Text
+ src/Bio/Sequence/Alignment.hs view
@@ -0,0 +1,59 @@+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE BangPatterns #-}+{-# OPTIONS_GHC -fno-warn-incomplete-patterns -fno-warn-name-shadowing #-}++module Bio.Sequence.Alignment+    ( Substitution, Gap, Alignment (..)+    , alignment+    , mkGlobal, mkLocal, mkSemiglobal, mkEditDistance+    ) where++import           Data.Array                   (array, range, (!))+import           Data.ByteString.Char8        (ByteString)+import qualified Data.ByteString.Char8        as B++import           Bio.Sequence.Alignment.Internal.Instances+import           Bio.Sequence.Alignment.Internal.Type++alignment :: Alignment a => a -> ByteString -> ByteString -> (Int, (ByteString, ByteString))+alignment sa s t = (score, trace sm sn si ti)+  where (m, n) = (B.length s, B.length t)+        bounds = ((0, 0), (m, n))++        (needGaps, (sm, sn)) = selector sa matrix+        (si, ti) = if needGaps then tails else ([], [])++        score = matrix ! (sm, sn)+        gapSymbol = '-'++        tails :: (String, String)+        tails | m == sm = (gaps (n - sn), B.unpack (B.drop sn t))+              | n == sn = (B.unpack (B.drop sm s), gaps (m - sm))++        gaps :: Int -> String+        gaps size = replicate size gapSymbol++        distance :: Int -> Int -> Int+        distance i 0 = inits sa i+        distance 0 j = inits sa j+        distance i j = maximum [ matrix ! (i - 1, j - 1) + sub i j+                               , matrix ! (i - 1, j) + g+                               , matrix ! (i, j - 1) + g+                               , additional sa+                               ]+          where !g = gap sa++        sub :: Substitution Int+        sub = subIJ sa s t++        matrix :: Matrix+        !matrix = array bounds [(ij, uncurry distance ij) | ij <- range bounds]++        trace :: Int -> Int -> String -> String -> (ByteString, ByteString)+        trace i j s' t' | isStop  matrix s t i j = (B.pack s', B.pack t')+                        | isVert  matrix s t i j = trace (i - 1) j (addToS i) (gapSymbol:t')+                        | isHoriz matrix s t i j = trace i (j - 1) (gapSymbol:s') (addToT j)+                        | isDiag  matrix s t i j = trace (i - 1) (j - 1) (addToS i) (addToT j)+          where addToS i = (s `B.index` (i - 1)):s'+                addToT j = (t `B.index` (j - 1)):t'+                Conditions {..} = conditions sa
+ src/Bio/Sequence/Alignment/Internal/Instances.hs view
@@ -0,0 +1,116 @@+{-# LANGUAGE BangPatterns  #-}+{-# LANGUAGE TupleSections #-}+{-# OPTIONS_GHC -fno-warn-incomplete-patterns -fno-warn-unused-matches #-}++module Bio.Sequence.Alignment.Internal.Instances where++import           Control.Monad                        (ap)+import           Data.Array                           (assocs, bounds, (!))+import           Data.ByteString.Char8                (ByteString)+import qualified Data.ByteString.Char8                as B+import           Data.List                            (maximumBy)++import           Bio.Sequence.Alignment.Internal.Type++data EditDistance = EditDistance++data AlignmentType = GlobalAlignment+                   | LocalAlignment+                   | SemiglobalAlignment+  deriving (Show, Eq)++data SimpleAlignment = SimpleAlignment { aType :: AlignmentType+                                       , subst :: Substitution Char+                                       , aGap  :: Gap+                                       }++instance Alignment EditDistance where+  gap _ = -1+  substitution _ c d | c == d    = 0+                     | otherwise = -1+  conditions = defaultConds+  selector ed mat = let (_, sp) = bounds mat in (True, sp)+  inits ed = (* gap ed)+  additional _ = minBound++instance Alignment SimpleAlignment where+  gap = aGap+  substitution = subst+  conditions sa | aType sa == LocalAlignment      = localConds sa+                | aType sa == SemiglobalAlignment = semiConds sa+                | otherwise                       = defaultConds sa+  selector sa mat | aType sa == GlobalAlignment     = (False, snd $ bounds mat)+                  | aType sa == LocalAlignment      = (False, localStart mat)+                  | aType sa == SemiglobalAlignment = (True, semiglobalStart mat)+  inits sa | aType sa == GlobalAlignment = (* gap sa)+           | otherwise                   = const 0+  additional sa | aType sa == LocalAlignment = 0+                | otherwise                  = minBound++mkGlobal :: Substitution Char -> Gap -> SimpleAlignment+mkGlobal = SimpleAlignment GlobalAlignment++mkLocal :: Substitution Char -> Gap -> SimpleAlignment+mkLocal = SimpleAlignment LocalAlignment++mkSemiglobal :: Substitution Char -> Gap -> SimpleAlignment+mkSemiglobal = SimpleAlignment SemiglobalAlignment++mkEditDistance :: EditDistance+mkEditDistance = EditDistance+++-- Default helpers++subIJ :: Alignment a => a -> ByteString -> ByteString -> Substitution Int+subIJ sa s t i j = sub (s `B.index` (i - 1)) (t `B.index` (j - 1))+  where !sub = substitution sa+{-# INLINE subIJ #-}++localStart :: Matrix -> (Int, Int)+localStart = listKeyByValMax . assocs++semiglobalStart :: Matrix -> (Int, Int)+semiglobalStart mat = listKeyByValMax $ lastRow ++ lastCol+  where lastRow = ap (,) (mat !) . (me,) <$> [ns..ne]+        lastCol = ap (,) (mat !) . (,ne) <$> [ms..me]+        ((ms, ns), (me, ne)) = bounds mat++localConds :: Alignment a => a -> Conditions+localConds a = (defaultConds a) { isStop = localStop a }++defaultConds :: Alignment a => a -> Conditions+defaultConds a = Conditions { isStop = defaultStop a+                            , isDiag = defaultDiag a+                            , isVert = defaultVert a+                            , isHoriz = defaultHoriz a+                            }++semiConds :: Alignment a => a -> Conditions+semiConds a = Conditions { isStop = defaultStop a+                         , isDiag = defaultDiag a+                         , isVert = \m s t i j -> j == 0 || (i /= 0 && m ! (i, j) == m ! (i - 1, j) + gap a)+                         , isHoriz = \m s t i j -> i == 0 || (j /= 0 && m ! (i, j) == m ! (i, j - 1) + gap a)+                         }++localStop :: Alignment a => a -> Condition+localStop _ m _ _ i j = i == 0 || j == 0 || m ! (i, j) == 0++defaultStop :: Alignment a => a -> Condition+defaultStop _ _ _ _ i j = i == 0 && j == 0++defaultDiag :: Alignment a => a -> Condition+defaultDiag sa m s t i j = i /= 0 && j /= 0 && m ! (i, j) == m ! (i - 1, j - 1) + sub i j+  where sub = subIJ sa s t++defaultVert :: Alignment a => a -> Condition+defaultVert sa m s t i j = i /= 0 && m ! (i, j) == m ! (i - 1, j) + gap sa++defaultHoriz :: Alignment a => a -> Condition+defaultHoriz sa m s t i j = j /= 0 && m ! (i, j) == m ! (i, j - 1) + gap sa++listKeyByValMax :: Ord b => [(a, b)] -> a+listKeyByValMax = fst . maximumBy elemsOrd+  where elemsOrd (_, x) (_, y) | x == y = EQ+                               | x <  y = LT+                               | x >  y = GT
+ src/Bio/Sequence/Alignment/Internal/Matrix/Scoring.hs view
@@ -0,0 +1,23 @@+{-# LANGUAGE BangPatterns #-}+{-# OPTIONS_GHC -fno-warn-incomplete-patterns -fno-warn-name-shadowing #-}++module Bio.Sequence.Alignment.Internal.Matrix.Scoring where++import           Control.Applicative                  (liftA2)+import           Data.List                            (words)++import           Bio.Sequence.Alignment.Internal.Type++class ScoringMatrix a where+  scoring :: a -> Substitution Char++loadMatrix :: String -> [((Char, Char), Int)]+loadMatrix txt = concat table+  where f = liftA2 (||) null ((/= '#') . head)+        strip = reverse . dropWhile (== ' ') . reverse . dropWhile (== ' ')+        !txtlns = filter f (strip <$> lines txt)+        !letters = (map head . words . head) txtlns+        !table = (map (lineMap . words) . tail) txtlns+        lineMap (x:xs) = let !hx = head x+                             f (n, c) = ((hx, c), n)+                         in f <$> (read <$> xs) `zip` letters
+ src/Bio/Sequence/Alignment/Internal/Matrix/Template.hs view
@@ -0,0 +1,51 @@+{-# LANGUAGE TemplateHaskell #-}++module Bio.Sequence.Alignment.Internal.Matrix.Template where++import           Data.Char                         (toLower)+import           Language.Haskell.TH+import           Language.Haskell.TH.Quote++import           Bio.Sequence.Alignment.Internal.Type+import           Bio.Sequence.Alignment.Internal.Matrix.Scoring++matrix :: QuasiQuoter+matrix = QuasiQuoter { quotePat = undefined+                     , quoteType = undefined+                     , quoteExp = undefined+                     , quoteDec = matrixDec+                     }+++matrixDec :: String -> Q [Dec]+matrixDec s = do let slines = lines s+                 let txt = (unlines . tail) slines+                 let name = head slines+                 (typeName, dataDecl) <- typeDec name+                 (funcName, funDecls) <- functionDec name txt+                 smDecl <- instDec typeName funcName+                 return $ dataDecl : smDecl : funDecls++instDec :: Name -> Name -> Q Dec+instDec typeN funN = return $ decl [body]+  where decl = InstanceD Nothing [] (AppT (ConT ''ScoringMatrix) (ConT typeN))+        body = FunD 'scoring [Clause [WildP] (NormalB (VarE funN)) []]++typeDec :: String -> Q (Name, Dec)+typeDec name = do typeN <- newName name+                  let dataN = mkName (nameBase typeN)+                  let dervs = [ConT ''Show, ConT ''Eq]+                  return (typeN, DataD [] typeN [] Nothing [NormalC dataN []] dervs)++functionDec :: String -> String -> Q (Name, [Dec])+functionDec name txt = do let subM = loadMatrix txt+                          funName <- newName (toLower <$> name)+                          let funSign = SigD funName (AppT (ConT ''Substitution) (ConT ''Char))+                          let clauses = mkClause <$> subM+                          let funDecl = FunD funName clauses+                          return (funName, [funSign, funDecl])++mkClause :: ((Char, Char), Int) -> Clause+mkClause ((c, d), i) = Clause [litC c, litC d] (NormalB (litI i)) []+  where litC = LitP . CharL+        litI = LitE . IntegerL . fromIntegral
+ src/Bio/Sequence/Alignment/Internal/Type.hs view
@@ -0,0 +1,35 @@+module Bio.Sequence.Alignment.Internal.Type where++import           Data.Array     (Array)+import Data.ByteString.Char8    (ByteString)++-- |Represents alignment matrix+type Matrix = Array (Int, Int) Int++-- |Substitution function for 'a' values comparison+type Substitution a = a -> a -> Int++-- |Gap type+type Gap = Int++-- |Condition, that gets matrix, 'i' and 'j'+type Condition = Matrix -> ByteString -> ByteString -> Int -> Int -> Bool++-- |A set of traceback conditions+data Conditions = Conditions { isStop  :: Condition -- ^Should we stop?+                             , isDiag  :: Condition -- ^Should we go daigonally?+                             , isVert  :: Condition -- ^Should we go vertically?+                             , isHoriz :: Condition -- ^Should we go horizontally?+                             }++-- |Traceback starting point selector function, bool indicate if we have to add gaps to sequence+type StartSelector = Matrix -> (Bool, (Int, Int))++-- |Introduces all useful methods to create an alignment+class Alignment a where+  gap :: a -> Gap+  substitution :: a -> Substitution Char+  conditions :: a -> Conditions+  inits :: a -> Int -> Int+  selector :: a -> StartSelector+  additional :: a -> Int
+ src/Bio/Sequence/Alignment/Matrix.hs view
@@ -0,0 +1,110 @@+{-# LANGUAGE QuasiQuotes     #-}+{-# LANGUAGE TemplateHaskell #-}++module Bio.Sequence.Alignment.Matrix+    ( ScoringMatrix (..)+    , BLOSUM62 (..), PAM250 (..), NUC44 (..)+    , blosum62, pam250, nuc44+    , matrix+    ) where++import Bio.Sequence.Alignment.Internal.Matrix.Scoring+import Bio.Sequence.Alignment.Internal.Matrix.Template++[matrix|BLOSUM62+#  Matrix made by matblas from blosum62.iij+#  * column uses minimum score+#  BLOSUM Clustered Scoring Matrix in 1/2 Bit Units+#  Blocks Database = /data/blocks_5.0/blocks.dat+#  Cluster Percentage: >= 62+#  Entropy =   0.6979, Expected =  -0.5209+   A  R  N  D  C  Q  E  G  H  I  L  K  M  F  P  S  T  W  Y  V  B  Z  X  *+A  4 -1 -2 -2  0 -1 -1  0 -2 -1 -1 -1 -1 -2 -1  1  0 -3 -2  0 -2 -1  0 -4+R -1  5  0 -2 -3  1  0 -2  0 -3 -2  2 -1 -3 -2 -1 -1 -3 -2 -3 -1  0 -1 -4+N -2  0  6  1 -3  0  0  0  1 -3 -3  0 -2 -3 -2  1  0 -4 -2 -3  3  0 -1 -4+D -2 -2  1  6 -3  0  2 -1 -1 -3 -4 -1 -3 -3 -1  0 -1 -4 -3 -3  4  1 -1 -4+C  0 -3 -3 -3  9 -3 -4 -3 -3 -1 -1 -3 -1 -2 -3 -1 -1 -2 -2 -1 -3 -3 -2 -4+Q -1  1  0  0 -3  5  2 -2  0 -3 -2  1  0 -3 -1  0 -1 -2 -1 -2  0  3 -1 -4+E -1  0  0  2 -4  2  5 -2  0 -3 -3  1 -2 -3 -1  0 -1 -3 -2 -2  1  4 -1 -4+G  0 -2  0 -1 -3 -2 -2  6 -2 -4 -4 -2 -3 -3 -2  0 -2 -2 -3 -3 -1 -2 -1 -4+H -2  0  1 -1 -3  0  0 -2  8 -3 -3 -1 -2 -1 -2 -1 -2 -2  2 -3  0  0 -1 -4+I -1 -3 -3 -3 -1 -3 -3 -4 -3  4  2 -3  1  0 -3 -2 -1 -3 -1  3 -3 -3 -1 -4+L -1 -2 -3 -4 -1 -2 -3 -4 -3  2  4 -2  2  0 -3 -2 -1 -2 -1  1 -4 -3 -1 -4+K -1  2  0 -1 -3  1  1 -2 -1 -3 -2  5 -1 -3 -1  0 -1 -3 -2 -2  0  1 -1 -4+M -1 -1 -2 -3 -1  0 -2 -3 -2  1  2 -1  5  0 -2 -1 -1 -1 -1  1 -3 -1 -1 -4+F -2 -3 -3 -3 -2 -3 -3 -3 -1  0  0 -3  0  6 -4 -2 -2  1  3 -1 -3 -3 -1 -4+P -1 -2 -2 -1 -3 -1 -1 -2 -2 -3 -3 -1 -2 -4  7 -1 -1 -4 -3 -2 -2 -1 -2 -4+S  1 -1  1  0 -1  0  0  0 -1 -2 -2  0 -1 -2 -1  4  1 -3 -2 -2  0  0  0 -4+T  0 -1  0 -1 -1 -1 -1 -2 -2 -1 -1 -1 -1 -2 -1  1  5 -2 -2  0 -1 -1  0 -4+W -3 -3 -4 -4 -2 -2 -3 -2 -2 -3 -2 -3 -1  1 -4 -3 -2 11  2 -3 -4 -3 -2 -4+Y -2 -2 -2 -3 -2 -1 -2 -3  2 -1 -1 -2 -1  3 -3 -2 -2  2  7 -1 -3 -2 -1 -4+V  0 -3 -3 -3 -1 -2 -2 -3 -3  3  1 -2  1 -1 -2 -2  0 -3 -1  4 -3 -2 -1 -4+B -2 -1  3  4 -3  0  1 -1  0 -3 -4  0 -3 -3 -2  0 -1 -4 -3 -3  4  1 -1 -4+Z -1  0  0  1 -3  3  4 -2  0 -3 -3  1 -1 -3 -1  0 -1 -3 -2 -2  1  4 -1 -4+X  0 -1 -1 -1 -2 -1 -1 -1 -1 -1 -1 -1 -1 -1 -2  0  0 -2 -1 -1 -1 -1 -1 -4+* -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4  1+|]++[matrix|PAM250+#+# This matrix was produced by "pam" Version 1.0.6 [28-Jul-93]+#+# PAM 250 substitution matrix, scale = ln(2)/3 = 0.231049+#+# Expected score = -0.844, Entropy = 0.354 bits+#+# Lowest score = -8, Highest score = 17+#+   A  R  N  D  C  Q  E  G  H  I  L  K  M  F  P  S  T  W  Y  V  B  Z  X  *+A  2 -2  0  0 -2  0  0  1 -1 -1 -2 -1 -1 -3  1  1  1 -6 -3  0  0  0  0 -8+R -2  6  0 -1 -4  1 -1 -3  2 -2 -3  3  0 -4  0  0 -1  2 -4 -2 -1  0 -1 -8+N  0  0  2  2 -4  1  1  0  2 -2 -3  1 -2 -3  0  1  0 -4 -2 -2  2  1  0 -8+D  0 -1  2  4 -5  2  3  1  1 -2 -4  0 -3 -6 -1  0  0 -7 -4 -2  3  3 -1 -8+C -2 -4 -4 -5 12 -5 -5 -3 -3 -2 -6 -5 -5 -4 -3  0 -2 -8  0 -2 -4 -5 -3 -8+Q  0  1  1  2 -5  4  2 -1  3 -2 -2  1 -1 -5  0 -1 -1 -5 -4 -2  1  3 -1 -8+E  0 -1  1  3 -5  2  4  0  1 -2 -3  0 -2 -5 -1  0  0 -7 -4 -2  3  3 -1 -8+G  1 -3  0  1 -3 -1  0  5 -2 -3 -4 -2 -3 -5  0  1  0 -7 -5 -1  0  0 -1 -8+H -1  2  2  1 -3  3  1 -2  6 -2 -2  0 -2 -2  0 -1 -1 -3  0 -2  1  2 -1 -8+I -1 -2 -2 -2 -2 -2 -2 -3 -2  5  2 -2  2  1 -2 -1  0 -5 -1  4 -2 -2 -1 -8+L -2 -3 -3 -4 -6 -2 -3 -4 -2  2  6 -3  4  2 -3 -3 -2 -2 -1  2 -3 -3 -1 -8+K -1  3  1  0 -5  1  0 -2  0 -2 -3  5  0 -5 -1  0  0 -3 -4 -2  1  0 -1 -8+M -1  0 -2 -3 -5 -1 -2 -3 -2  2  4  0  6  0 -2 -2 -1 -4 -2  2 -2 -2 -1 -8+F -3 -4 -3 -6 -4 -5 -5 -5 -2  1  2 -5  0  9 -5 -3 -3  0  7 -1 -4 -5 -2 -8+P  1  0  0 -1 -3  0 -1  0  0 -2 -3 -1 -2 -5  6  1  0 -6 -5 -1 -1  0 -1 -8+S  1  0  1  0  0 -1  0  1 -1 -1 -3  0 -2 -3  1  2  1 -2 -3 -1  0  0  0 -8+T  1 -1  0  0 -2 -1  0  0 -1  0 -2  0 -1 -3  0  1  3 -5 -3  0  0 -1  0 -8+W -6  2 -4 -7 -8 -5 -7 -7 -3 -5 -2 -3 -4  0 -6 -2 -5 17  0 -6 -5 -6 -4 -8+Y -3 -4 -2 -4  0 -4 -4 -5  0 -1 -1 -4 -2  7 -5 -3 -3  0 10 -2 -3 -4 -2 -8+V  0 -2 -2 -2 -2 -2 -2 -1 -2  4  2 -2  2 -1 -1 -1  0 -6 -2  4 -2 -2 -1 -8+B  0 -1  2  3 -4  1  3  0  1 -2 -3  1 -2 -4 -1  0  0 -5 -3 -2  3  2 -1 -8+Z  0  0  1  3 -5  3  3  0  2 -2 -3  0 -2 -5  0  0 -1 -6 -4 -2  2  3 -1 -8+X  0 -1  0 -1 -3 -1 -1 -1 -1 -1 -1 -1 -1 -2 -1  0  0 -4 -2 -1 -1 -1 -1 -8+* -8 -8 -8 -8 -8 -8 -8 -8 -8 -8 -8 -8 -8 -8 -8 -8 -8 -8 -8 -8 -8 -8 -8  1+|]++[matrix|NUC44+#+# This matrix was created by Todd Lowe   12/10/92+#+# Uses ambiguous nucleotide codes, probabilities rounded to+#  nearest integer+#+# Lowest score = -4, Highest score = 5+#+    A   T   G   C   S   W   R   Y   K   M   B   V   H   D   N+A   5  -4  -4  -4  -4   1   1  -4  -4   1  -4  -1  -1  -1  -2+T  -4   5  -4  -4  -4   1  -4   1   1  -4  -1  -4  -1  -1  -2+G  -4  -4   5  -4   1  -4   1  -4   1  -4  -1  -1  -4  -1  -2+C  -4  -4  -4   5   1  -4  -4   1  -4   1  -1  -1  -1  -4  -2+S  -4  -4   1   1  -1  -4  -2  -2  -2  -2  -1  -1  -3  -3  -1+W   1   1  -4  -4  -4  -1  -2  -2  -2  -2  -3  -3  -1  -1  -1+R   1  -4   1  -4  -2  -2  -1  -4  -2  -2  -3  -1  -3  -1  -1+Y  -4   1  -4   1  -2  -2  -4  -1  -2  -2  -1  -3  -1  -3  -1+K  -4   1   1  -4  -2  -2  -2  -2  -1  -4  -1  -3  -3  -1  -1+M   1  -4  -4   1  -2  -2  -2  -2  -4  -1  -3  -1  -1  -3  -1+B  -4  -1  -1  -1  -1  -3  -3  -1  -1  -3  -1  -2  -2  -2  -1+V  -1  -4  -1  -1  -1  -3  -1  -3  -3  -1  -2  -1  -2  -2  -1+H  -1  -1  -4  -1  -3  -1  -3  -1  -3  -1  -2  -2  -1  -2  -1+D  -1  -1  -1  -4  -3  -1  -1  -3  -1  -3  -2  -2  -2  -1  -1+N  -2  -2  -2  -2  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1+|]
+ src/Bio/Sequence/Alignment/Scoring.hs view
@@ -0,0 +1,12 @@+module Bio.Sequence.Alignment.Scoring+  ( similarity+  , hamming+  , relativeHamming+  , alignmentScore+  , alignmentSemiglobalScore+  ) where++import           Bio.Sequence.Alignment.Scoring.Similarity (alignmentScore, alignmentSemiglobalScore,+                                                            hamming,+                                                            relativeHamming,+                                                            similarity)
+ src/Bio/Sequence/Alignment/Scoring/Similarity.hs view
@@ -0,0 +1,34 @@+module Bio.Sequence.Alignment.Scoring.Similarity+  ( similarity+  , hamming+  , relativeHamming+  , alignmentScore+  , alignmentSemiglobalScore+  ) where++import           Data.ByteString.Char8         (ByteString)+import qualified Data.ByteString.Char8         as B++import           Bio.Sequence.Alignment        (Substitution, alignment,+                                                mkGlobal, mkSemiglobal)+import           Bio.Sequence.Alignment.Matrix (blosum62)++similarity :: ByteString -> ByteString -> Float+similarity f s = 1 - fromIntegral (hamming f' s') / fromIntegral (B.length f')+  where (_, (f', s')) = alignment (mkGlobal blosum62 (-5)) f s++hamming :: ByteString -> ByteString -> Int+hamming f s = sum $ B.zipWith notTheSame f s+  where+    notTheSame :: Char -> Char -> Int+    notTheSame f' s' = if f' /= s' then 1 else 0++relativeHamming :: ByteString -> ByteString -> Float+relativeHamming f s = fromIntegral hammingValue / fromIntegral (B.length f)+  where hammingValue = hamming f s++alignmentScore :: Substitution Char -> ByteString -> ByteString -> Int+alignmentScore matrix f s = fst $ alignment (mkGlobal matrix (-5)) f s++alignmentSemiglobalScore :: Substitution Char -> ByteString -> ByteString -> Int+alignmentSemiglobalScore matrix f s = fst $ alignment (mkSemiglobal matrix (-5)) f s
+ src/Bio/Sequence/AminoAcid.hs view
@@ -0,0 +1,8 @@+module Bio.Sequence.AminoAcid+  ( AminoAcid (..)+  , shortName3, shortName, fromChar, fromShortCode+  ) where++import           Bio.Sequence.AminoAcid.Internal.Types (AminoAcid (..),+                                                        fromChar, fromShortCode,+                                                        shortName, shortName3)
+ src/Bio/Sequence/AminoAcid/Internal/Types.hs view
@@ -0,0 +1,112 @@+module Bio.Sequence.AminoAcid.Internal.Types+  ( AminoAcid (..)+  , shortName3, shortName, fromChar, fromShortCode+  ) where++import           Data.Char (toUpper)++data AminoAcid = Alanine | Glycine | Valine | Isoleucine | Leucine | Methionine+               | Phenylalanine | Tyrosine | Tryptophan | Serine | Threonine+               | Asparagine | Glutamine | Cysteine | Proline | Arginine+               | Histidine | Lysine | AsparticAcid | GlutamicAcid+               | AcetylGroup | MetilAmine+  deriving (Show, Read, Eq, Ord)++shortName3 :: AminoAcid -> String+shortName3 Alanine       = "Ala"+shortName3 Glycine       = "Gly"+shortName3 Valine        = "Val"+shortName3 Isoleucine    = "Ile"+shortName3 Leucine       = "Leu"+shortName3 Methionine    = "Met"+shortName3 Phenylalanine = "Phe"+shortName3 Tyrosine      = "Tyr"+shortName3 Tryptophan    = "Trp"+shortName3 Serine        = "Ser"+shortName3 Threonine     = "Thr"+shortName3 Asparagine    = "Asn"+shortName3 Glutamine     = "Gln"+shortName3 Cysteine      = "Cys"+shortName3 Proline       = "Pro"+shortName3 Arginine      = "Arg"+shortName3 Histidine     = "His"+shortName3 Lysine        = "Lys"+shortName3 AsparticAcid  = "Asp"+shortName3 GlutamicAcid  = "Glu"+shortName3 AcetylGroup   = "Ace"+shortName3 MetilAmine    = "Nma"++shortName :: AminoAcid -> Char+shortName Alanine       = 'A'+shortName Glycine       = 'G'+shortName Valine        = 'V'+shortName Isoleucine    = 'I'+shortName Leucine       = 'L'+shortName Methionine    = 'M'+shortName Phenylalanine = 'F'+shortName Tyrosine      = 'Y'+shortName Tryptophan    = 'W'+shortName Serine        = 'S'+shortName Threonine     = 'T'+shortName Asparagine    = 'N'+shortName Glutamine     = 'Q'+shortName Cysteine      = 'C'+shortName Proline       = 'P'+shortName Arginine      = 'R'+shortName Histidine     = 'H'+shortName Lysine        = 'K'+shortName AsparticAcid  = 'D'+shortName GlutamicAcid  = 'E'+shortName AcetylGroup   = '^'+shortName MetilAmine    = '$'++fromShortCode :: String -> AminoAcid+fromShortCode str = fromCode' $ toUpper <$> str+  where fromCode' "ALA" = Alanine+        fromCode' "GLY" = Glycine+        fromCode' "VAL" = Valine+        fromCode' "ILE" = Isoleucine+        fromCode' "LEU" = Leucine+        fromCode' "MET" = Methionine+        fromCode' "PHE" = Phenylalanine+        fromCode' "TYR" = Tyrosine+        fromCode' "TRP" = Tryptophan+        fromCode' "SER" = Serine+        fromCode' "THR" = Threonine+        fromCode' "ASN" = Asparagine+        fromCode' "GLN" = Glutamine+        fromCode' "CYS" = Cysteine+        fromCode' "PRO" = Proline+        fromCode' "ARG" = Arginine+        fromCode' "HIS" = Histidine+        fromCode' "LYS" = Lysine+        fromCode' "ASP" = AsparticAcid+        fromCode' "GLU" = GlutamicAcid+        fromCode' "ACE" = AcetylGroup+        fromCode' "NMA" = MetilAmine+        fromCode' code  = error $ "Unknown aminoacid code => " ++ code++fromChar :: Char -> AminoAcid+fromChar 'A'  = Alanine+fromChar 'G'  = Glycine+fromChar 'V'  = Valine+fromChar 'I'  = Isoleucine+fromChar 'L'  = Leucine+fromChar 'M'  = Methionine+fromChar 'F'  = Phenylalanine+fromChar 'Y'  = Tyrosine+fromChar 'W'  = Tryptophan+fromChar 'S'  = Serine+fromChar 'T'  = Threonine+fromChar 'N'  = Asparagine+fromChar 'Q'  = Glutamine+fromChar 'C'  = Cysteine+fromChar 'P'  = Proline+fromChar 'R'  = Arginine+fromChar 'H'  = Histidine+fromChar 'K'  = Lysine+fromChar 'D'  = AsparticAcid+fromChar 'E'  = GlutamicAcid+fromChar '^'  = AcetylGroup+fromChar '$'  = MetilAmine+fromChar code = error $ "Unknown aminoacid code => " ++ [code]
+ src/Bio/Sequence/Parser/Fasta.hs view
@@ -0,0 +1,7 @@+module Bio.Sequence.Parser.Fasta+  ( fastaParser+  , aminoParser+  ) where++import           Bio.Sequence.Parser.Fasta.Internal.Converters (aminoParser)+import           Bio.Sequence.Parser.Fasta.Internal.Parser     (fastaParser)
+ src/Bio/Sequence/Parser/Fasta/Internal/Converters.hs view
@@ -0,0 +1,17 @@+module Bio.Sequence.Parser.Fasta.Internal.Converters+  ( aminoParser++  ) where++import           Bio.Sequence                              (Chain (..),+                                                            Sequence)+import           Bio.Sequence.AminoAcid                    (AminoAcid (..),+                                                            fromChar)+import           Bio.Sequence.Parser.Fasta.Internal.Parser (fastaParser)+import           Text.Parsec.Text                          (Parser)++aminoParser :: Parser [Sequence AminoAcid]+aminoParser = (charSeqToAminoSeq <$>) <$> fastaParser++charSeqToAminoSeq :: Sequence Char -> Sequence AminoAcid+charSeqToAminoSeq (Chain name residues) = Chain name (fromChar <$> residues)
+ src/Bio/Sequence/Parser/Fasta/Internal/Parser.hs view
@@ -0,0 +1,36 @@+module Bio.Sequence.Parser.Fasta.Internal.Parser+  ( fastaParser+  ) where++import           Bio.Sequence     (Chain (..), Sequence)+import           Data.Text        as T (Text, concat, pack, strip, unpack)+import           Text.Parsec      (char, letter, many, many1, newline, noneOf,+                                   spaces)+import           Text.Parsec.Text (Parser)++data FastaSequence = FastaSequence { sName    :: Text+                                   , residues :: Text+                                   } deriving (Show)++fastaParser :: Parser [Sequence Char]+fastaParser = (fastaSequenceToSequence <$>) <$> many fastaSequence++fastaSequenceToSequence :: FastaSequence -> Sequence Char+fastaSequenceToSequence fs = Chain { chainType = sName fs+                                   , chainResidues = unpack (residues fs)+                                   }++fastaSequence :: Parser FastaSequence+fastaSequence = FastaSequence <$> nameP <*> sequenceP++nameP :: Parser Text+nameP = strip <$> (T.pack <$> nameP')++nameP' :: Parser String+nameP' =  char '>' *> many (noneOf ['\n']) <* newline++sequenceP :: Parser Text+sequenceP = T.concat <$> many lineP++lineP :: Parser Text+lineP = T.pack <$> many1 letter <* spaces
+ test/Spec.hs view
@@ -0,0 +1,63 @@+{-# LANGUAGE OverloadedStrings #-}++import           Test.Hspec++import Data.Monoid ((<>))+import Data.ByteString.Char8 (ByteString)++import Bio.Sequence.Alignment+import Bio.Sequence.Alignment.Matrix++chains :: [ByteString]+chains = [ "EVQLVESGGGLVQPGGSLRLSCAASGFNIKDTYIHWVRQAPGKGLEWVA" <>+           "RIYPTNGYTRYADSVKGRFTISADTSKNTAYLQMNSLRAEDTAVYYCSRWGGDGFYAMDYWGQGTLVTVSS"+         , "EVQLVESGGGLVQPGGSLRLSCAASGFTFTDYTMDWVRQAPGKGLEWVA" <>+           "DVNPNSGGSIYNQRFKGRFTLSVDRSKNTLYLQMNSLRAEDTAVYYCARNLGPSFYFDYWGQGTLVTVSS"+         , "QVQLQQPGAELVKPGASVKMSCKASGYTFTSYNMHWVKQTPGRGLEWIG" <>+           "AIYPGNGDTSYNQKFKGKATLTADKSSSTAYMQLSSLTSEDSAVYYCARSTYYGGDWYFNVWGAGTTVTVSA"+         , "EVQLVESGGGLVQPGRSLRLSCAASGFTFDDYAMHWVRQAPGKGLEWVSAI" <>+           "TWNSGHIDYADSVEGRFTISRDNAKNSLYLQMNSLRAEDTAVYCAKVSYLSTASSLDYWGQGTLVTVSS"+         , "EVQLVESGGGLVQPGGSLRLSCAASGYTFTNYGMNWVRQAPGKGLEWVG" <>+           "WINTYTGEPTYAADFKRRFTFSLDTSKSTAYLQMNSLRAEDTAVYCAKYPHYYGSSHWYFDVWGQGTLVTVSS"+         , "QVQLVQSGVEVKKPGASVKVSCKASGYTFTNYYMYWVRQAPGQGLEWMG" <>+           "GINPSNGGTNFNEKFKNRVTLTTDSSTTTAYMELKSLQFDDTAVYYCARRDYRFDMGFDYWGQGTTVTVSS"+         , "EVQLVESGGGLVQPGGSLRLSCAASGFTFSNYWMNWVRQAPGKGLEWVA" <>+           "AINQDGSEKYYVGSVKGRFTISRDNAKNSLYLQMNSLRVEDTAVYYCVRDYYDILTDYYIHYWYFDLWGRGTLVTVSS"+         ]++combinations :: [Int]+combinations = [fst $ alignment glob x y | x <- chains, y <- chains]+  where glob = mkGlobal blosum62 (-5)++results :: [Int]+results = [ 645, 459, 345, 431, 401, 337, 405, 459, 634, 375, 437, 444+          , 378, 425, 345, 375, 651, 306, 368, 418, 316, 431, 437, 306+          , 628, 413, 312, 423, 401, 444, 368, 413, 669, 337, 436, 337+          , 378, 418, 312, 337, 647, 304, 405, 425, 316, 423, 436, 304, 688]++main :: IO ()+main = hspec $ do+         describe "Edit distance" $ do+           it "align empty strings" $ do+             let (_, (s', t')) = alignment mkEditDistance "" ""+             s' `shouldBe` ""+             t' `shouldBe` ""+           it "align equal strings" $ do+             let (_, (s', t')) = alignment mkEditDistance "AAA" "AAA"+             s' `shouldBe` "AAA"+             t' `shouldBe` "AAA"+         describe "Semiglobal alignment" $ do+           it "align without error" $ do+             let s = "SVAPGQTARITCGEESLGSRSVIWYQQRPGQAPSLIIYNNNDRPSGIPDRFSGSPGSTFGTTATLTITSVEAGDEADYYCHIWDSRRPTNWVFGEGTTLIVL"+             let t = "SSMSVSPGETAKISCGKESIGSRAVQWYQQKPGQPPSLIIYNNQDRPAGVPERFSASPDFRPGTTATLTITNVDAEDEADYYCHIYDARGGTNWVFDRGTTLTVL"+             let (_, (s', _)) = alignment (mkSemiglobal blosum62 (-5)) s t+             s' `shouldBe` "---SVAPGQTARITCGEESLGSRSVIWYQQRPGQAPSLIIYNNNDRPSGIPDRFSGSPGSTFGTTATLTITSVEAGDEADYYCHIWDSRRPTNWVFGEGTTLIVL"+         describe "Global alignment" $ do+           it "align antibodies" $ do+             let (tra : per : _) = chains+             let (score, (s', t')) = alignment (mkGlobal blosum62 (-5)) tra per+             s' `shouldBe` "EVQLVESGGGLVQPGGSLRLSCAASGFNIKDTY-IHWVRQAPGKGLEWVARIYPTNGYTRYADSVKGRFTISADTSKNTAYLQMNSLRAEDTAVYYCSRWGGDGFYAMDYWGQGTLVTVSS"+             t' `shouldBe` "EVQLVESGGGLVQPGGSLRLSCAASGFTFTD-YTMDWVRQAPGKGLEWVADVNPNSGGSIYNQRFKGRFTLSVDRSKNTLYLQMNSLRAEDTAVYYCARNLGPSFY-FDYWGQGTLVTVSS"+             score `shouldBe` 459+           it "align fast" $+             combinations `shouldBe` results
+ test/SpecSimilarity.hs view
@@ -0,0 +1,19 @@+{-# LANGUAGE OverloadedStrings #-}++import           Test.Hspec++import           Data.ByteString.Char8          (ByteString)++import           Bio.Sequence.Alignment.Scoring (similarity)++main :: IO ()+main = hspec $+         describe "Similarity" $+           it "simple strings" $ do+             let sourceS = "QQYDLFIS" :: ByteString+             let cdr31 = "KQSYDLPT" :: ByteString+             let cdr32 = "QQYSDDPT" :: ByteString+             let sim1 = similarity sourceS cdr31+             let sim2 = similarity sourceS cdr32+             sim1 `shouldBe` 0.44444442+             sim2 `shouldBe` 0.44444442