{-# Language DeriveDataTypeable #-} module FilterSFF (main) where -- import Debug.Trace import System.IO import System.Console.CmdArgs as C import Version import Generations.GenBase import Generations.GS20 import Generations.Titanium import Generations.Empirical generations :: [(String,Generation)] generations = [("GS20", gs20), ("Titanium",titanium),("EmpTitanium",tiEmp)] data Opts = Opts { generation :: String , output, inputs :: FilePath , count :: Bool } deriving (Data,Typeable,Show) defopt :: Opts defopt = Opts { generation = "Titanium" &= help "454 generation" &= typ "GEN" &= C.name "G" , output = "filtered.sff" &= typFile , inputs = "" &= args &= typFile , count = False &= help "count matches instead of filtering" } &= program "filtersff" &= summary ("filtersff "++version) main :: IO () main = do opts <- cmdArgs defopt SFF h rs <- readSFF (inputs opts) case lookup (generation opts) generations of Just g -> if count opts then apply_count (disc_filters g) rs else do let f = apply_filter (disc_filters g) n <- writeSFF' (output opts) (SFF h $ f rs) putStrLn ("Wrote "++show n++" records to "++output opts) Nothing -> error ("Unknown generation: '"++generation opts++"'") apply_filter :: [DiscardFilter] -> [ReadBlock] -> [ReadBlock] apply_filter filters = filter (\r -> (and (apply1 filters r))) apply_count :: [DiscardFilter] -> [ReadBlock] -> IO () apply_count filters rbs = go (replicate (length filters) 0) rbs where go :: [Int] -> [ReadBlock] -> IO () go counts (r:rs) = do let fs = apply1 filters r if and fs then go counts rs else do let c = add counts fs trace (show c) go c rs go counts [] = trace (show counts++"\n") {- -- This leaks (well, retains) memory. Laziness be damned. apply_trace :: [DiscardFilter] -> [ReadBlock] -> [ReadBlock] apply_trace filters = go (replicate (length filters) 0) where go counts (r:rs) = let fs = apply1 filters r in if and fs then r : go counts rs else let c = add counts fs in trace ("Filtered: "++show c) $ go counts rs go _ [] = trace "\n" [] -} trace :: String -> IO () trace msg = hPutStr stderr ("\r"++msg) -- apply fs = filter (\r -> not (and $ apply1 fs r)) add :: [Int] -> [Bool] -> [Int] add cs = zipWith (+) cs . map (fromEnum . not) apply1 :: [DiscardFilter] -> ReadBlock -> [Bool] apply1 filters r = map ($r) filters