packages feed

gact-0.1: src/GACT.hs

{-# Language PackageImports #-}

module Main where

import "biopsl" Bio.Alignment.PSL
-- import Bio.Sequence (SeqData)
import qualified Data.HashSet as S
import Data.List (partition,foldl',sortBy)
import qualified Data.ByteString.Lazy.Char8 as B
import Data.Hashable

import Options

main :: IO ()
main = do
  opts <- getArgs
  pss <- mapM readPSL $ files opts
  mapM_ (if long_output opts then print_cluster else print_list) . cluster_sl qname tname . concat $ pss

print_list :: (S.HashSet B.ByteString, [PSL]) -> IO ()
print_list (s,_) = B.putStrLn . B.unwords . S.toList $ s

print_cluster :: (S.HashSet B.ByteString, [PSL]) -> IO ()
print_cluster (s,b) = do 
  B.putStrLn . B.unwords . S.toList $ s
  B.putStrLn $ unparsePSL $ sortOn tname $ sortOn tstarts $ b

sortOn :: Ord a1 => (a -> a1) -> [a] -> [a]
sortOn f = sortBy (\x y -> compare (f x) (f y))

cluster_sl  :: (Hashable a, Ord a) => (b->a) -> (b->a) -> [b] -> [(S.HashSet a,[b])]
cluster_sl f1 f2 = foldl' csl []
    where csl cs b = 
              -- can be short circuited for more performance
              let (acs,tmp)   = partition (S.member (f1 b) . fst) cs
                  (bcs,rest)  = partition (S.member (f2 b) . fst) tmp
              in case (acs,bcs) of 
                   ([(ao,as)],[(bo,bs)]) -> (S.union ao bo,b:as++bs):rest
                   ([(ao,as)],[])        -> (S.insert (f2 b) ao, b:as):rest
                   ([],[(bo,bs)])        -> (S.insert (f1 b) bo, b:bs):rest
                   ([],[])               -> (S.fromList [f1 b,f2 b],[b]):rest
                   _                     -> error "Grave mistake"

select :: (t -> Bool) -> [t] -> ([t],[t])
select p = go []
  where go acc (x:xs) | p x = ([x],acc++xs)
                      | otherwise = go (x:acc) xs
        go acc [] = ([],acc)