module Bio.Alignment.AAlign (
local_score, local_align
, global_score, global_align
) where
import Data.List (partition,maximumBy)
import Bio.Sequence.SeqData
import Bio.Alignment.AlignData
minf :: Num a => a
minf = 100000000
global_score :: (Num a, Ord a) => SubstMx t a -> (a,a) -> Sequence t -> Sequence t -> a
global_score mx g s1 s2 = uncurry max . last . last
$ columns (score_select minf mx g) (0,fst g) s1 s2
local_score :: (Num a, Ord a) => SubstMx t a -> (a,a) -> Sequence t -> Sequence t -> a
local_score mx g s1 s2 = maximum . map (uncurry max) . concat
$ columns (score_select 0 mx g) (0,fst g) s1 s2
score_select :: (Num a,Ord a) => a -> SubstMx t a -> (a,a) -> Selector (a,a)
score_select minf mx (go,ge) cds =
let (reps,ids) = partition (isRepl.snd) cds
s = maximum $ minf:[max sub gap +mx (x,y) | ((sub,gap),Repl x y) <- reps]
g = maximum $ minf:[max (sub+go) (gap+ge) | ((sub,gap),_) <- ids]
in (s,g)
max' (x,ax) (y,yx) = if x>=y then (x,ax) else (y,yx)
fp (x,ax) (s,e) = (x+s,e:ax)
global_align :: (Num a, Ord a) => SubstMx t a -> (a,a) -> Sequence t -> Sequence t -> (a,EditList)
global_align mx g s1 s2 = revsnd . uncurry max' . last . last
$ columns (align_select minf mx g) ((0,[]),(fst g,[])) s1 s2
local_align :: (Num a, Ord a) => SubstMx t a -> (a,a) -> Sequence t -> Sequence t -> (a,EditList)
local_align mx g s1 s2 = revsnd . maximumBy (compare `on` fst)
. map (uncurry max') . concat
$ columns (align_select 0 mx g) ((0,[]),(fst g,[])) s1 s2
revsnd (s,a) = (s,reverse a)
align_select :: (Num a, Ord a) => a -> SubstMx t a -> (a,a) -> Selector ((a,EditList),(a,EditList))
align_select minf mx (go,ge) cds =
let (reps,ids) = partition (isRepl.snd) cds
s = maximumBy (compare `on` fst)
$ (minf,[]):[max' sub gap `fp` (mx (x,y),e) | ((sub,gap),e@(Repl x y)) <- reps]
g = maximumBy (compare `on` fst)
$ (minf,[]):[max' (sub `fp` (go,e)) (gap `fp` (ge,e)) | ((sub,gap),e) <- ids]
in (s,g)