{-# LANGUAGE DeriveGeneric #-}
module ELynx.Data.Character.Codon
( Codon (Codon),
unsafeFromVec,
UniversalCode (..),
translate,
translateX,
translateI,
)
where
import Data.Aeson
( FromJSON,
ToJSON,
)
import Data.List
import qualified Data.Map as M
import qualified Data.Vector.Generic as V
import qualified ELynx.Data.Character.AminoAcidI as AI
import ELynx.Data.Character.AminoAcidS
import qualified ELynx.Data.Character.Character as C
import qualified ELynx.Data.Character.Nucleotide as N
import qualified ELynx.Data.Character.NucleotideI as NI
import qualified ELynx.Data.Character.NucleotideX as NX
import GHC.Generics (Generic)
newtype Codon a = Codon (a, a, a)
deriving (Show, Read, Eq, Ord)
convert :: (C.Character a, C.Character b) => Codon a -> Codon b
convert (Codon (x, y, z)) = Codon (C.convert x, C.convert y, C.convert z)
unsafeFromVec :: V.Vector v a => v a -> Codon a
unsafeFromVec xs =
Codon (V.head xs, V.head . V.tail $ xs, V.head . V.tail . V.tail $ xs)
data UniversalCode = Standard | VertebrateMitochondrial
deriving (Show, Read, Eq, Ord, Enum, Bounded, Generic)
instance FromJSON UniversalCode
instance ToJSON UniversalCode
mapFromLists :: Ord a => [a] -> [a] -> [a] -> [b] -> M.Map (Codon a) b
mapFromLists xs ys zs as =
M.fromList $ zipWith4 (\f s t a -> (Codon (f, s, t), a)) xs ys zs as
nucs :: Enum a => [a]
nucs = map toEnum [3, 1, 0, 2]
base1, base2, base3 :: Enum a => [a]
base1 = [n | n <- nucs, _ <- [0 .. 3 :: Int], _ <- [0 .. 3 :: Int]]
base2 = [n | _ <- [0 .. 3 :: Int], n <- nucs, _ <- [0 .. 3 :: Int]]
base3 = [n | _ <- [0 .. 3 :: Int], _ <- [0 .. 3 :: Int], n <- nucs]
standard :: [AminoAcidS]
standard =
[ F,
F,
L,
L,
S,
S,
S,
S,
Y,
Y,
Stop,
Stop,
C,
C,
Stop,
W,
L,
L,
L,
L,
P,
P,
P,
P,
H,
H,
Q,
Q,
R,
R,
R,
R,
I,
I,
I,
M,
T,
T,
T,
T,
N,
N,
K,
K,
S,
S,
R,
R,
V,
V,
V,
V,
A,
A,
A,
A,
D,
D,
E,
E,
G,
G,
G,
G
]
vertebrateMitochondrial :: [AminoAcidS]
vertebrateMitochondrial =
[ F,
F,
L,
L,
S,
S,
S,
S,
Y,
Y,
Stop,
Stop,
C,
C,
W,
W,
L,
L,
L,
L,
P,
P,
P,
P,
H,
H,
Q,
Q,
R,
R,
R,
R,
I,
I,
M,
M,
T,
T,
T,
T,
N,
N,
K,
K,
S,
S,
Stop,
Stop,
V,
V,
V,
V,
A,
A,
A,
A,
D,
D,
E,
E,
G,
G,
G,
G
]
translate :: UniversalCode -> Codon N.Nucleotide -> AminoAcidS
translate code = (M.!) (universalCode code)
translateX :: UniversalCode -> Codon NX.NucleotideX -> AminoAcidS
translateX code codon@(Codon (x, y, z))
| C.isGap x || C.isGap y || C.isGap z = Gap
| otherwise = C.convert . translate code . convert $ codon
translateI :: UniversalCode -> Codon NI.NucleotideI -> AI.AminoAcidI
translateI code codon@(Codon (x, y, z))
| C.isIUPAC x || C.isIUPAC y || C.isIUPAC z = AI.X
| otherwise = C.convert . translateX code . convert $ codon
universalCode :: UniversalCode -> M.Map (Codon N.Nucleotide) AminoAcidS
universalCode Standard = mapFromLists base1 base2 base3 standard
universalCode VertebrateMitochondrial =
mapFromLists base1 base2 base3 vertebrateMitochondrial