diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,3 @@
+#!/usr/bin/env runhaskell
+import Distribution.Simple
+main = defaultMain
diff --git a/flowsim.cabal b/flowsim.cabal
new file mode 100644
--- /dev/null
+++ b/flowsim.cabal
@@ -0,0 +1,35 @@
+Name:           flowsim
+Version:        0.2.6
+License:        GPL
+
+Author:         Ketil Malde
+Maintainer:     Ketil Malde <ketil@malde.org>
+
+Category:       Bioinformatics
+Synopsis:       Simulate 454 pyrosequencing
+Description:    pyrosim - a simulator for 454 pyrosequencing data
+                Simulate shotgun sequencing with Roche's 454 sequencing technology.
+                .
+                The Darcs repository is at <http://malde.org/~ketil/biohaskell/pyrosim>.
+
+HomePage:       http://bhlog.malde.org/
+Build-Depends:  bio >= 0.4.4, base >= 4 && <= 5, array >= 0.1, bytestring >= 0.9.1, random, MonadRandom, cmdargs, containers, directory
+Build-Type:     Simple
+Tested-with:    GHC==6.8.2
+
+ -- Data-files:     README
+Executable:     flowsim
+Main-Is:        FlowSim.hs
+Other-Modules:  Statistics, Config, EmpFile
+		Generations.GenBase, Generations.GS20, 
+		Generations.Titanium, Generations.Empirical
+Hs-Source-Dirs: src
+
+Executable:     hplc
+Main-Is:        HPLCount.hs
+Ghc-Options:    -main-is HPLCount
+Hs-Source-Dirs: src
+
+Executable:	clonesim
+Main-Is:	CloneSim.hs
+Hs-Source-Dirs: src
diff --git a/src/CloneSim.hs b/src/CloneSim.hs
new file mode 100644
--- /dev/null
+++ b/src/CloneSim.hs
@@ -0,0 +1,82 @@
+{- | CloneSim - fragment a genome sequence to simulate cloning
+     Factored out from flowsim in order to separate clone generation
+     from flow simulation and base calling.
+-}
+
+{-# Language DeriveDataTypeable #-}
+
+module Main where
+
+import Bio.Sequence hiding ((!))
+import Statistics
+
+import System.IO (stdin,stdout,stderr,hPutStrLn)
+import Control.Monad (forM)
+import qualified Data.ByteString.Lazy as B
+import Data.Int (Int64)
+import System.Console.CmdArgs
+import Data.Array
+
+type Dist    = String
+data Conf = Conf 
+            { lengths :: Dist
+            , count :: Int
+            , input :: [FilePath]
+            } deriving (Data,Typeable,Show)
+
+modes :: Mode Conf
+modes = mode $ Conf {  
+    lengths = "Uniform 400 800" &= text "model for clone lengths" & typ "DIST"
+  , count = 10                &= text "number of reads to generate" & typ "INT"
+  , input = def &= args & typFile
+  } &= prog "clonesim"
+    & text "simulate sequence cloning"
+    & helpSuffix ["Available distributions (DIST):" 
+                 ,"    Uniform a b, Normal mu sigma, LogNormal mu sigma"]
+
+version :: String
+version = "clonesim v0.2.6, copyright 2010 Ketil Malde" 
+
+data Dir   = Fwd | Rev deriving (Eq,Enum,Bounded)
+
+instance Random Dir where 
+  random g = let (b,g') = random g in (if b then Fwd else Rev,g')
+  randomR = error "randomR is undefined for Dir"
+
+main :: IO ()
+main = do
+  conf <- cmdArgs version [modes]
+  -- print conf
+  let inf = case input conf of 
+        []  -> hPutStrLn stderr "clonesim: reading from stdin" >> hReadFasta stdin
+        [x] -> readFasta x
+        _   -> error "Please specify only a single input file"
+  ss <- map (defragSeq . castToNuc) `fmap` inf
+  let sa = listArray (0,length ss-1) ss
+  hWriteFasta stdout =<< evalRandIO (simulate conf sa)
+  
+type SeqArray = Array Int (Sequence Nuc)
+
+-- | the real 'main'
+simulate :: RandomGen g => Conf -> SeqArray -> Rand g [Sequence Nuc]
+simulate conf sa = do
+  let ldist   = read $ lengths conf
+      (_,asz) = bounds sa
+  forM [1..count conf] $ const 
+    (do i <- floor `fmap` sample (Uniform 0 $ 1+fromIntegral asz) -- inclusive?
+        let s = sa!i
+        p <- round `fmap` sample (Uniform 0 $ fromIntegral (seqlength s-1))
+        l <- round `fmap` sample ldist
+        dir <- getRandom
+        return (mkClone dir p l s))
+    
+mkClone :: Dir -> Int64 -> Int64 -> Sequence Nuc -> Sequence Nuc
+mkClone dir pos len (Seq h s mq) = 
+  Seq (fromStr (toStr h++" "++show pos++case dir of Fwd -> "+"; Rev -> "-"))
+      sd
+      qual
+    where sd = B.take len
+               . (case dir of Fwd -> snd; Rev -> revcompl' . fst) 
+               . B.splitAt pos $ s
+          qual = B.take len `fmap` case dir of Fwd -> fst; Rev -> snd 
+                 `fmap` B.splitAt pos `fmap` mq
diff --git a/src/Config.hs b/src/Config.hs
new file mode 100644
--- /dev/null
+++ b/src/Config.hs
@@ -0,0 +1,147 @@
+{-| Module Config - replaces Options, use CmdArgs instead -}
+{-# LANGUAGE DeriveDataTypeable #-}
+
+module Config (Config(..), mkconf
+              ,inform, whenLoud, whenNotQuiet) where
+
+import Data.Char (toLower)
+import Data.List (isPrefixOf, intersperse)
+import System.Console.CmdArgs
+import System.Directory (doesFileExist)
+import Control.Monad (when)
+import System.IO (hPutStrLn, stderr, stdin)
+import EmpFile
+
+import Bio.Sequence
+
+import Generations.GenBase
+import Generations.GS20
+import Generations.Titanium
+import Generations.Empirical
+
+version :: String
+version = "flowsim v0.2.6, copyright 2010 Ketil Malde"
+
+-- data GenName = Titanium | FLX | GS20 deriving (Typeable, Data, Show, Eq)
+type GenName = String
+type Dist    = String
+
+data Config = Conf { generation :: GenName
+                   , degradation:: Dist
+                   , model  :: FilePath
+                   , qualmethod  :: GenName
+                   , discardfilters :: [String]
+                   , trimfilters :: [String]
+                   , flowkey :: String
+                   , hplinput :: FilePath
+                   , flowlength :: Int
+                   , flowcycle :: String
+                   , inputs :: [FilePath]
+                   , output :: FilePath
+                   } deriving (Typeable, Data, Show, Read)
+
+modes :: Mode Config
+modes = mode $ Conf 
+  { generation     = "Titanium" &= text "454 generation to simulate"           & typ "GEN"   & flag "G"
+  , degradation    = def &= text "model for degradation of the flow model" & typ "DIST"
+  , model          = def &= text "empirical distribution for flow generation" & typFile
+  , qualmethod     = def &= text "method for calculating quality"          & typ "STRING"
+  , discardfilters = def &= text "discarding filters to apply"             & typ "DFILT"
+  , trimfilters    = def &= text "trimming filters to apply"               & typ "TFILT"
+  , flowkey        = def &= text "sequence key to start each read (TCAG)"
+  , hplinput       = def &= text "input genome for HPL count estimate" & typFile
+  , flowlength     = def &= text "number of flow cycles to run"
+  , flowcycle      = def &= text "sequence nucleotides in each flow cycle (TACG)"
+  , inputs         = def &= args & typFile
+  , output         = def &= text "output file"
+  } &= prog "flowsim"
+    & text "simulate 454 pyrosequencing."
+    & helpSuffix hs
+      where     
+        hs = ["Generations (GEN): "++concat (intersperse ", " $ map fst generations)
+             , "Distributions (DIST): Uniform a b, Normal mu sigma, LogNormal mu sigma"
+             , "Discarding filters (DFILT): ...."
+             , "Trimming filters (TFILT): ...."]
+    
+mkconf :: IO (Generation,IO [Sequence Nuc],HPLprob,FilePath)
+mkconf = do
+  cf <- cmdArgs version [modes]
+  let inp = map castToNuc `fmap` if null (inputs cf) then hReadFasta stdin else concat `fmap` mapM readFasta (inputs cf)
+  gen <- mkgen cf
+  whenLoud $ inform ("Generation: "++generation cf ++ "\n" ++ show gen)
+  when (null $ output cf) $ error "Please specify an output file with -o"
+  hplc <- case hplinput cf of 
+    []   -> return default_hplc
+    file -> (mkHPLprobs . freqtable . concatMap (hpls (f_cycle gen) . seqdata)) `fmap` readFasta file
+  return (gen, inp, hplc, output cf)
+  
+default_hplc :: HPLprob
+default_hplc _ l = 3/4**fromIntegral l
+
+generations :: [(GenName,Generation)]
+generations = [("GS20", gs20), ("Titanium",titanium),("EmpTitanium",tiEmp)]
+
+lookupGen :: String -> Generation 
+lookupGen g = case map snd . filter (isPrefixOf (map toLower g) . map toLower . fst) $ generations of
+  [x] -> x
+  _ -> error ("Generation '"++g++"' is non-existing or ambigous\nAvailable generations are: "++show (map fst generations))
+
+-- if non-null, pick field f from generation str, else pick it from the default
+setFromGen :: Generation -> (Generation -> field) -> String -> field
+setFromGen dflt f str = if null str then f dflt else f (lookupGen str)
+
+-- similar, but use Read to parse the string
+setFromStr :: (Read a) => Generation -> (Generation -> a) -> String -> a
+setFromStr dflt f str = if null str then f dflt else read str
+  
+mkgen :: Config -> IO Generation  
+mkgen (Conf g deg fm qm df tf fk hpl fl fc _inputs _output) = do
+  let gen = lookupGen g
+      setG = setFromGen gen
+      setD = setFromStr gen 
+      setF fs | null fs   = disc_filters gen
+              | otherwise = concatMap (maybe [] id) $ map (flip lookup filterlist) fs
+      setT fs | null fs   = trim_filters gen
+              | otherwise = concatMap (maybe [] id) $ map (flip lookup trimlist) fs
+      my_qcall = if null qm then qcall gen 
+                 else case qm of 
+                   "gs20tab" -> qual_gs20_tab
+                   "dexact"  -> qual_exact_decreasing
+                   "fexact"  -> qual_exact_fixed 
+                   _ -> error ("No such quality call method:"++show qm
+                               ++"\nAvailable methods: gs20tab, dexact, fexact.")
+  my_model <- if null fm then return (models gen)
+              else do
+                f <- doesFileExist fm
+                ms <- if f then readPdf fm else return (parse_models fm)
+                return $ combine_models (models gen) ms
+  return $ gen  
+          { qcall        = my_qcall
+          , degrade      = setD degrade deg
+          , models       = my_model
+          , disc_filters = setF df 
+          , trim_filters = setT tf
+          , f_key        = setG f_key fk
+          , f_len        = if fl > 0 then fl else f_len gen
+          , f_cycle      = setG f_cycle fc
+          }
+
+parse_models :: String -> [Distribution]
+parse_models str = read ("["++str++"]")
+
+-- filterlist :: [DiscardFilter]
+filterlist = [] -- todo: export from SFF_filters
+
+-- trimlist  :: [Trimfilter]
+trimlist   = [] 
+
+-- Logging
+inform :: String -> IO ()
+inform = hPutStrLn stderr
+
+whenLoud, whenNotQuiet :: IO () -> IO ()
+whenLoud action = flip when action =<< isLoud
+-- note that isQuiet = return False in CmdArgs!
+whenNotQuiet action = do  n <- isNormal
+                          l <- isLoud
+                          when (n || l) action
diff --git a/src/EmpFile.hs b/src/EmpFile.hs
new file mode 100644
--- /dev/null
+++ b/src/EmpFile.hs
@@ -0,0 +1,25 @@
+module EmpFile where
+
+import Statistics
+import Control.Monad (when)
+
+readPdf :: FilePath -> IO [Distribution]
+readPdf f = do 
+  cs <- lines `fmap` readFile f
+  return (parsePdf ("file '"++f++"'") cs)  
+  
+parsePdf :: String -> [String] -> [Distribution]
+parsePdf f cs = 
+  let (_:fs:vss) = transpose (map words cs)
+  in if (or $ zipWith (/=) [0..] (map read fs))
+     then error ("Flow index from "++f++" isn't [0..]!")
+     else map (fromPdf 0 0.01 . map (P . read)) vss
+
+transpose xs = let r0 = map head xs  
+                   rest = map tail xs
+               in if any null rest then [r0] else r0 : transpose rest
+
+-- currently this only works for a single model
+combine_models :: [Int -> Distribution] -> [Distribution] -> [Int -> Distribution]
+combine_models [f] ds = [\i -> if i < length ds then ds!!i else f i]
+combine_models _ _ = error "Can't combine multiple models"
diff --git a/src/FlowSim.hs b/src/FlowSim.hs
new file mode 100644
--- /dev/null
+++ b/src/FlowSim.hs
@@ -0,0 +1,186 @@
+{- | FlowSim - simulate 454 flowgrams from a reference genome 
+
+   Flow values are modelled from a log-normal noise, and a sequence of
+   normal distributions, one for each homopolymer length.  These distributions
+   can be estimated from real data.
+
+   Todo:
+   * Paired ends models B-linker-A
+   * Support multiple sequences:
+      - scan seqs + lenghts
+      - gen n numbers (0..total length), transform to deltas (cf. rselect)
+      - sort and generate
+
+-}
+{-# options -XParallelListComp #-}
+
+module Main where
+
+import Bio.Sequence
+import Bio.Sequence.SFF
+
+import qualified Data.ByteString.Lazy.Char8 as B
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.ByteString.Char8 as BS
+import qualified Data.ByteString as BS2
+
+import Data.Char (toUpper)
+import Data.Int
+
+import Statistics
+import Generations.GenBase
+import Config
+
+import Control.Monad (when)
+
+-- ------------------------------------------------------------
+-- picking random postions/directions for reads
+
+data Dir   = Fwd | Rev deriving (Eq,Enum,Bounded)
+
+instance Random Dir where 
+  random g = let (b,g') = random g in (if b then Fwd else Rev,g')
+  randomR = error "randomR is undefined for Dir"
+
+main :: IO ()
+main = do
+  (gen,is,hplc,o) <- mkconf
+  
+  ss <- is
+  case ss of [] -> error ("Input appears to be empty?")
+             _ -> return ()
+  sff <- evalRandIO $ sim454 gen hplc ss
+  n <- writeSFF' o sff
+  whenLoud $ inform ("Wrote "++show n++" reads to '"++o++"'.")
+
+-- testing
+test_s :: Sequence Nuc
+test_s = Seq (fromStr "foo") (fromStr "aacacattcgtggtnagctacggaacacattcgtggtnagctacggaacacattcgtggtnagctacggaacacattcgtggtnagctacgg") Nothing
+
+-- | Heavy lifting.  Building an SFF file from the specified information
+sim454 :: RandomGen g => Generation -> HPLprob -> [Sequence Nuc] -> Rand g SFF
+sim454 gen hplc ss = do
+  let ch = makeCommonHeader gen
+      tf r = foldr ($) r $ trim_filters gen 
+      df r = and $ zipWith ($) (disc_filters gen) (repeat r)
+  rbs <- map tf `fmap` filter df `fmap` mapM (\s -> makeReadBlock gen hplc s ch) ss
+  return (SFF ch rbs)
+
+-- Generate a sequence of models
+-- The generation specifies a series of initial models, this function
+-- uses these with the degradation to generate a progression of models to use  
+makeModels :: RandomGen g => Generation -> Rand g [Model]  
+makeModels gen = case models gen of
+  [m] -> iterativeWorsen (f_len gen) (degrade gen) m
+  im@(_:_) -> do
+    let ns = f_len gen `div` length im
+    return $ concat $ map (replicate ns) im
+
+iterativeWorsen :: RandomGen g => Int -> Distribution -> Model -> Rand g [Model]
+iterativeWorsen 0 _ _ = return []
+iterativeWorsen count deg m = do 
+  ps <- perturbs 1 count
+  return $ zipWith (fmap . worsen) ps $ replicate count m
+    where perturbs _   0 = return []
+          perturbs cur n = do 
+            w <- sample deg
+            let new = cur+w
+            rest <- perturbs new (n-1)
+            return (new : rest)
+
+-- --------------------------------------------------
+-- Generate the flow values
+
+-- generate the "absolute" flow values from the cycle and the origin sequence data
+makeFlows :: [Char] -> SeqData -> [(Char,Int)]
+makeFlows c s | B.null s = []
+              | otherwise = let (c1,s1) = makeCycle [] (take 4 c) s 
+                                s2 = case B.uncons s1 of Just (x,_) -> if not (toUpper x `elem` "ACGT") then B.tail s1 else s1; _ -> s1
+                            in c1 ++ makeFlows c s2
+
+makeCycle :: [(Char,Int)] -> [Char] -> SeqData -> ([(Char,Int)],SeqData)
+makeCycle acc []     s = (reverse acc, s)
+makeCycle acc (c:cs) s = let (this,rest) = B.span ((==toUpper c).toUpper) s
+                         in makeCycle ((c,fromIntegral $ B.length this):acc) cs rest
+
+-- | Takes a sequence of flows with exact homopolymer lengths, 
+-- permutes and calls them.  Next step is prepareData
+permuteAndCall :: RandomGen g => Generation -> HPLprob -> [(Char,Int)] -> 
+                  Rand g [(Flow,[Char],[Qual])]
+permuteAndCall gen hplc fs = do
+  -- when (trace (show fs) False) (return ())
+  let n  = fromIntegral $ f_len gen
+      flow_cont = drop (length fs `mod` length (f_cycle gen)) $ cycle (f_cycle gen)
+      xs = fs ++ zip flow_cont (replicate (n-length fs) 0)
+  ms <- makeModels gen
+  -- if and $ zipWith (==) (map fst xs) (cycle $ f_cycle gen) then return () 
+  -- else error (map fst xs ++ "\n don't cycle: "++f_cycle gen)
+  sequence $ take n $ zipWith (my_call (qcall gen) hplc) ms xs
+
+-- Titanium base/quality calling
+my_call :: RandomGen g => QualMethod -> HPLprob -> Model -> (Char,Int) -> 
+           Rand g (Flow,[Char],[Qual])
+my_call qm ft md (c,hpl) = do
+  f <- sample (md hpl)
+  let fi = max 0 . round . (100*) $ f
+      n = fromIntegral ((fi+50) `div` 100)
+      cs = replicate n c
+      qs = qm ft md (c,fi)
+  when (length qs /= n) $ error ("Qual mismatch: "++show (f,fi,n,cs,qs))
+  return (fi, cs, qs)
+
+-- | Somewhat advanced unzip, calculating the index in the process.
+--   Also replace three consequtive empty lists with Ns
+convertCalls :: [(Flow,[Char],[Qual])] -> ([Flow],[Char],[Qual],[Int])
+convertCalls = go 0 . addDots
+  where go _ [] = ([],[],[],[])
+        go p ((f,cs,qs):fs) 
+          | null cs = let (f',c',q',i') = go (p+1) fs
+                      in (f:f',c',q',i')
+          | otherwise = let (f',c',q',i') = go 0 fs
+                        in (f:f',cs++c',qs++q',(p+1):replicate (length cs-1) 0 ++ i')
+        
+        addDots ((f1,cs1,qs1):(f2,cs2,qs2):(f3,cs3,qs3):(f4,cs4,qs4):rest)
+            | null cs1 && null cs2 && null cs3 && not (null cs4) = (f1,cs1,qs1):(f2,cs2,qs2):(f3,"N",[0]):addDots ((f4,cs4,qs4):rest)
+            | otherwise = (f1,cs1,qs1) : addDots ((f2,cs2,qs2):(f3,cs3,qs3):(f4,cs4,qs4):rest)
+        addDots fewerThanThree = fewerThanThree
+
+-- | Generate a ReadBlock
+--   direction and position chosen at random, and encoded in the read name
+makeReadBlock :: RandomGen g => Generation -> HPLprob -> Sequence Nuc -> CommonHeader -> Rand g ReadBlock
+makeReadBlock g hplc sq ch = do
+       let sdata = seqdata sq
+           rn = BS.concat $ BL.toChunks $ seqlabel sq
+           fs = makeFlows (BS.unpack $ flow ch) $ BL.concat [BL.fromChunks [key ch], {- B.take (floor cl) $ -} sdata]
+       (pfs,cs,qs,is) <- convertCalls `fmap` permuteAndCall g hplc fs
+       return $ verifyRB (flow_length ch) $ ReadBlock {
+                           read_header = ReadHeader {
+                                           name_length                 = fromIntegral $ BS.length rn -- :: Int16
+                                         , num_bases                   = fromIntegral $ length cs    -- :: Int32
+                                         , clip_qual_left              = 5                           -- :: Int16
+                                         , clip_qual_right             = fromIntegral $ length cs    -- :: Int16
+                                         , clip_adapter_left           = 0 -- :: Int16
+                                         , clip_adapter_right          = 0 -- :: Int16
+                                         , read_name                   = rn -- :: ByteString
+                                         }
+                         -- The data block
+                          , flow_data        = packFlows pfs    -- :: [Flow]
+                          , flow_index       = BS2.pack $ map fromIntegral is -- :: ByteString
+                          , bases            = fromStr cs -- :: SeqData
+                          , quality          = BL.pack qs -- :: QualData
+                          }
+
+-- | Consistency check on generated ReadBlocks.
+verifyRB :: Int16 -> ReadBlock -> ReadBlock
+verifyRB fl rb 
+            | name_length rh == 0  = err "name_length is zero"
+            | num_bases rh == 0    = err "num_bases is zero"
+--            | clip_qual_left rh > clip_qual_right rh = err "clipping gives negative sequence"
+            | BS2.length (read_name rh) /= (fromIntegral $ name_length rh)  = err "read_name has incorrect length"
+            | BS.length (flow_data rb) `div` 2 /= fromIntegral fl  = err ("Number of flows ("++show (BS.length (flow_data rb) `div` 2)++")do not match flow_length of "++show fl++" in CommonHeader")
+            | BS.length (flow_data rb) `div` 2 < (fromIntegral $ sum $ BS2.unpack $ flow_index rb) = err "flow_index longer than flows"
+            | B.length (bases rb) /= (fromIntegral $ BS.length $ flow_index rb) = err ("bases ("++show (B.length (bases rb))++") and flow_index ("++show (BS.length $ flow_index rb)++") have different lengths")
+            | B.length (quality rb) /= (fromIntegral $ BS.length $ flow_index rb) = err ("quality ("++show (B.length (quality rb))++") and flow_index ("++show (BS.length $ flow_index rb)++") have different lengths")
+            | otherwise = rb
+    where rh = read_header rb 
+          err str = error (str ++ "\n" ++ show rb)
diff --git a/src/Generations/Empirical.hs b/src/Generations/Empirical.hs
new file mode 100644
# file too large to diff: src/Generations/Empirical.hs
diff --git a/src/Generations/GS20.hs b/src/Generations/GS20.hs
new file mode 100644
--- /dev/null
+++ b/src/Generations/GS20.hs
@@ -0,0 +1,157 @@
+module Generations.GS20 where
+
+import Generations.GenBase
+
+import Data.Array
+import qualified Data.ByteString.Char8 as BC
+import qualified Data.ByteString as B
+import Control.Monad (when)
+
+type QualTable = Array Flow B.ByteString
+
+-- | Wrapper around 'array' that interpolates missing values
+--   Todo: make this more sophisticated!
+mkQualTable :: (Flow,Flow) -> [(Flow,B.ByteString)] -> QualTable
+mkQualTable is = array is . map extend . interpolate
+
+interpolate :: [(Flow,B.ByteString)] -> [(Flow,B.ByteString)]
+interpolate ((x1,y1):(x2,y2):rest)
+              = [(x,y1) | x <- [x1..x2-1]]++interpolate ((x2,y2):rest)
+interpolate xs = xs
+
+extend :: (Flow,B.ByteString)-> (Flow,B.ByteString)
+extend (x,y) = let delta = ((x+50) `div` 100) - fromIntegral (B.length y)
+               in (x,B.concat [y,B.replicate (fromIntegral delta) 1])
+
+gs20 :: Generation
+gs20 = Gen {
+         name     = "GS20"
+       , models    = [\h -> let h' = fromIntegral h 
+                            in if h == 0 then LogNormal (negate 2.5) 0.2 else Normal h' (0.04+0.06*h')]
+       , qcall = qual_gs20_tab
+       , degrade  = Normal 0.005 0.002
+       , disc_filters = [filter_key,filter_empty]
+       , trim_filters = []
+      
+       , f_key        = "TCAG"
+       , f_len        = 168 -- :: Int16
+       , f_cycle      = "TACG"
+       }
+
+
+qual_gs20_tab :: QualMethod
+qual_gs20_tab _ _ (_,fi) = B.unpack (gs20qt!fi)
+
+gs20qt :: QualTable
+gs20qt = mkQualTable (0,3100) $ map (\(x,y) -> (x,BC.pack y)) [
+             (0,""),(1,""),(2,""),(3,""),(4,""),(5,""),(6,""),(7,""),(8,""),(9,""),(10,"")
+            ,(11,""),(12,""),(13,""),(14,""),(15,""),(16,""),(17,""),(18,""),(19,""),(20,"")
+            ,(21,""),(22,""),(23,""),(24,""),(25,""),(26,""),(27,""),(28,""),(29,""),(30,"")
+            ,(31,""),(32,""),(33,""),(34,""),(35,""),(36,""),(37,""),(38,""),(39,"")
+            ,(40,""),(41,""),(42,""),(43,""),(44,""),(45,""),(46,""),(47,""),(48,""),(49,"")
+            ,(50,"\b"),(51,"\b"),(52,"\b"),(53,"\t"),(54,"\t"),(55,"\n"),(56,"\n"),(57,"\n"),(58,"\n"),(59,"\v")
+            ,(60,"\v"),(61,"\f"),(62,"\r"),(63,"\r"),(64,"\r"),(65,"\r"),(66,"\SO"),(67,"\SI"),(68,"\SI"),(69,"\DLE")
+            ,(70,"\DLE"),(71,"\DC1"),(72,"\DC1"),(73,"\DC1"),(74,"\DC2"),(75,"\DC3"),(76,"\DC3"),(77,"\DC3"),(78,"\DC4"),(79,"\NAK")
+            ,(80,"\NAK"),(81,"\NAK"),(82,"\SYN"),(83,"\ETB"),(84,"\ETB"),(85,"\ETB"),(86,"\CAN"),(87,"\CAN"),(88,"\EM"),(89,"\EM")
+            ,(90,"\SUB"),(91,"\SUB"),(92,"\SUB"),(93,"\SUB"),(94,"\ESC"),(95,"\ESC"),(96,"\ESC"),(97,"\ESC"),(98,"\FS"),(99,"\FS")
+            ,(100,"\FS"),(101,"\FS"),(102,"\FS"),(103,"\FS"),(104,"\FS"),(105,"\FS"),(106,"\FS"),(107,"\FS"),(108,"\FS"),(109,"\FS")
+            ,(110,"\FS"),(111,"\FS"),(112,"\ESC"),(113,"\ESC"),(114,"\ESC"),(115,"\SUB"),(116,"\SUB"),(117,"\SUB"),(118,"\EM"),(119,"\EM")
+            ,(120,"\CAN"),(121,"\CAN"),(122,"\CAN"),(123,"\ETB"),(124,"\ETB"),(125,"\ETB"),(126,"\SYN"),(127,"\SYN"),(128,"\SYN"),(129,"\SYN")
+            ,(130,"\NAK"),(131,"\NAK"),(132,"\NAK"),(133,"\DC4"),(134,"\DC4"),(135,"\DC4"),(136,"\DC4"),(137,"\DC4"),(138,"\DC4"),(139,"\DC3")
+            ,(140,"\DC3"),(141,"\DC3"),(142,"\DC3"),(143,"\DC3"),(144,"\DC3"),(145,"\DC3"),(146,"\DC3"),(147,"\DC3"),(148,"\DC4"),(149,"\DC4")
+            ,(150,"\DC4\EOT"),(151,"\DC4\ENQ"),(152,"\DC4\ENQ"),(153,"\DC4\ENQ"),(154,"\NAK\ACK"),(155,"\NAK\ACK"),(156,"\NAK\a"),(157,"\NAK\a"),(158,"\SYN\b"),(159,"\SYN\b")
+            ,(160,"\SYN\b"),(161,"\ETB\t"),(162,"\ETB\t"),(163,"\CAN\n"),(164,"\CAN\v"),(165,"\CAN\v"),(166,"\EM\f"),(167,"\EM\f"),(168,"\EM\f"),(169,"\SUB\r")
+            ,(170,"\SUB\r"),(171,"\SUB\SO"),(172,"\ESC\SI"),(173,"\ESC\SI"),(174,"\FS\DLE"),(175,"\FS\DLE"),(176,"\FS\DC1"),(177,"\GS\DC1"),(178,"\GS\DC1"),(179,"\GS\DC2")
+            ,(180,"\RS\DC2"),(181,"\RS\DC2"),(182,"\RS\DC3"),(183,"\US\DC4"),(184,"\US\DC4"),(185,"\US\DC4"),(186,"\US\NAK"),(187," \NAK"),(188," \NAK"),(189," \SYN")
+            ,(190," \SYN"),(191,"!\ETB"),(192,"!\ETB"),(193,"!\ETB"),(194,"!\ETB"),(195,"\"\CAN"),(196,"\"\CAN"),(197,"\"\CAN"),(198,"\"\CAN"),(199,"\"\EM")
+            ,(200,"\"\EM"),(201,"#\EM"),(202,"#\EM"),(203,"#\EM"),(204,"#\SUB"),(205,"#\SUB"),(206,"#\SUB"),(207,"#\SUB"),(208,"#\SUB"),(209,"#\SUB")
+            ,(210,"#\SUB"),(211,"#\SUB"),(212,"#\SUB"),(213,"#\SUB"),(214,"#\SUB"),(215,"#\SUB"),(216,"#\SUB"),(217,"#\SUB"),(218,"#\SUB"),(219,"#\SUB")
+            ,(220,"#\SUB"),(221,"#\SUB"),(222,"#\SUB"),(223,"#\SUB"),(224,"#\SUB"),(225,"#\SUB"),(226,"#\SUB"),(227,"\"\SUB"),(228,"\"\SUB"),(229,"\"\SUB")
+            ,(230,"\"\SUB"),(231,"\"\SUB"),(232,"\"\SUB"),(233,"\"\SUB"),(234,"\"\SUB"),(235,"\"\SUB"),(236,"\"\SUB"),(237,"!\SUB"),(238,"!\EM"),(239,"!\EM")
+            ,(240,"!\EM"),(241,"!\EM"),(242,"!\EM"),(243,"!\EM"),(244,"!\EM"),(245,"!\EM"),(246,"!\EM"),(247,"!\EM"),(248,"!\EM"),(249,"!\EM")
+            ,(250,"!\EM\SOH"),(251,"!\EM\SOH"),(252,"!\EM\SOH"),(253,"!\EM\SOH"),(254,"!\EM\STX"),(255,"!\EM\STX"),(256,"!\EM\STX"),(257,"!\EM\STX"),(258,"!\EM\STX"),(259,"!\EM\STX")
+            ,(260,"!\SUB\ETX"),(261,"!\SUB\ETX"),(262,"!\SUB\ETX"),(263,"!\SUB\ETX"),(264,"!\SUB\ETX"),(265,"!\SUB\EOT"),(266,"!\SUB\EOT"),(267,"!\SUB\EOT"),(268,"!\SUB\EOT"),(269,"\"\ESC\ENQ")
+            ,(270,"\"\ESC\ENQ"),(271,"\"\ESC\ENQ"),(272,"\"\ESC\ENQ"),(273,"\"\ESC\ACK"),(274,"\"\ESC\ACK"),(275,"#\FS\ACK"),(276,"#\FS\ACK"),(277,"#\FS\a"),(278,"#\FS\a"),(279,"#\FS\a")
+            ,(280,"#\FS\a"),(281,"#\FS\b"),(282,"#\FS\b"),(283,"$\GS\b"),(284,"$\GS\b"),(285,"$\GS\t"),(286,"$\GS\t"),(287,"$\GS\t"),(288,"$\RS\t"),(289,"$\RS\t")
+            ,(290,"%\RS\n"),(291,"%\RS\n"),(292,"%\RS\n"),(293,"%\RS\n"),(294,"%\RS\n"),(295,"%\RS\v"),(296,"%\RS\v"),(297,"%\US\v"),(298,"%\US\v"),(299,"&\US\f")
+            ,(300,"&\US\f"),(301,"&\US\f"),(302,"&\US\f"),(303,"&\US\f"),(304,"&\US\f"),(305,"&\US\r"),(306,"&\US\r"),(307,"&\US\r"),(308,"& \r"),(309,"& \r")
+            ,(310,"& \r"),(311,"& \r"),(312,"& \SO"),(313,"& \SO"),(314,"& \SO"),(315,"& \SO"),(316,"& \SO"),(317,"' \SO"),(318,"' \SO"),(319,"' \SO")
+            ,(320,"' \SO"),(321,"' \SO"),(322,"' \SI"),(323,"' \SI"),(324,"' \SI"),(325,"& \SI"),(326,"& \SI"),(327,"& \SI"),(328,"& \SI"),(329,"& \SI")
+            ,(330,"& \SI"),(331,"& \SI"),(332,"& \SI"),(333,"& \SI"),(334,"& \SI"),(335,"& \SI"),(336,"& \SI"),(337,"& \SI"),(338,"& \SI"),(339,"& \SI")
+            ,(340,"& \SI"),(341,"& \SI"),(342,"& \SI"),(343,"&\US\SI"),(344,"&\US\SI"),(345,"&\US\SI"),(346,"&\US\SI"),(347,"&\US\DLE"),(348,"&\US\DLE"),(349,"&\US\DLE")
+            ,(350,"&\US\DLE"),(351,"&\US\DLE\SOH"),(352,"&\US\DLE\SOH"),(353,"&\US\DLE\SOH"),(354,"&\US\DLE\SOH"),(355,"&\US\DLE\SOH"),(356,"&\US\DLE\SOH"),(357,"&\US\DLE\SOH"),(358,"&\US\DLE\SOH"),(359,"&\US\DLE\SOH")
+            ,(360,"&\US\DLE\STX"),(361,"&\US\DLE\STX"),(362,"&\US\DLE\STX"),(363,"&\US\DLE\STX"),(364,"&\US\DLE\STX"),(365,"&\US\DLE\STX"),(366,"& \DLE\STX"),(367,"& \DLE\STX"),(368,"& \DC1\STX"),(369,"& \DC1\ETX")
+            ,(370,"& \DC1\ETX"),(371,"& \DC1\ETX"),(372,"& \DC1\ETX"),(373,"& \DC1\ETX"),(374,"& \DC1\ETX"),(375,"& \DC1\ETX"),(376,"' \DC1\EOT"),(377,"' \DC1\EOT"),(378,"' \DC1\EOT"),(379,"' \DC1\EOT")
+            ,(380,"' \DC1\EOT"),(381,"' \DC2\EOT"),(382,"' \DC2\EOT"),(383,"' \DC2\EOT"),(384,"' \DC2\EOT"),(385,"' \DC2\EOT"),(386,"' \DC2\ENQ"),(387,"' \DC2\ENQ"),(388,"'!\DC2\ENQ"),(389,"'!\DC2\ENQ")
+            ,(390,"'!\DC2\ENQ"),(391,"'!\DC2\ENQ"),(392,"'!\DC2\ENQ"),(393,"'!\DC3\ACK"),(394,"(!\DC3\ACK"),(395,"(!\DC3\ACK"),(396,"(!\DC3\ACK"),(397,"(!\DC3\ACK"),(398,"(!\DC3\ACK"),(399,"(!\DC3\ACK")
+            ,(400,"(!\DC3\ACK"),(401,"(!\DC3\a"),(402,"(!\DC3\a"),(403,"(!\DC3\a"),(404,"(!\DC3\a"),(405,"(!\DC4\a"),(406,"(!\DC4\a"),(407,"(!\DC4\a"),(408,"(!\DC4\a"),(409,"(!\DC4\a")
+            ,(410,"(\"\DC4\b"),(411,"(\"\DC4\b"),(412,"(\"\DC4\b"),(413,"(\"\DC4\b"),(414,"(\"\DC4\b"),(415,"(\"\DC4\b"),(416,"(\"\DC4\b"),(417,"(\"\DC4\b"),(418,"(\"\DC4\b"),(419,")\"\DC4\b")
+            ,(420,")\"\DC4\t"),(421,")\"\DC4\t"),(422,")\"\DC4\t"),(423,")\"\DC4\t"),(424,")\"\DC4\t"),(425,")\"\DC4\t"),(426,")\"\NAK\t"),(427,")\"\NAK\t"),(428,")\"\NAK\t"),(429,")\"\NAK\t")
+            ,(430,")\"\NAK\t"),(431,")\"\NAK\t"),(432,")\"\NAK\t"),(433,")\"\NAK\t"),(434,")\"\NAK\n"),(435,")\"\NAK\n"),(436,")\"\NAK\n"),(437,")\"\NAK\n"),(438,")\"\NAK\n"),(439,")\"\NAK\n")
+            ,(440,")\"\NAK\n"),(441,")\"\NAK\n"),(442,")\"\NAK\n"),(443,")\"\NAK\n"),(444,")\"\NAK\n"),(445,")\"\NAK\n"),(446,")\"\NAK\n"),(447,")\"\NAK\n"),(448,")\"\NAK\n"),(449,")\"\NAK\n")
+            ,(450,")\"\NAK\n"),(451,")\"\NAK\n\SOH"),(452,")\"\NAK\n\SOH"),(453,")\"\NAK\n\SOH"),(454,")\"\NAK\v\SOH"),(455,")\"\NAK\v\SOH"),(456,")\"\NAK\v\SOH"),(457,")\"\NAK\v\SOH"),(458,")\"\NAK\v\SOH"),(459,")\"\NAK\v\SOH")
+            ,(460,")\"\NAK\v\SOH"),(461,")\"\NAK\v\SOH"),(462,")\"\NAK\v\SOH"),(463,")\"\NAK\v\SOH"),(464,")\"\NAK\v\SOH"),(465,")\"\NAK\v\SOH"),(466,")\"\NAK\v\SOH"),(467,")\"\NAK\v\SOH"),(468,")!\NAK\v\SOH"),(469,")!\NAK\v\SOH")
+            ,(470,")!\NAK\v\SOH"),(471,")!\NAK\v\SOH"),(472,")!\NAK\v\SOH"),(473,")!\NAK\v\STX"),(474,")\"\NAK\v\STX"),(475,")\"\NAK\v\STX"),(476,")\"\NAK\v\STX"),(477,")\"\NAK\v\STX"),(478,")\"\NAK\f\STX"),(479,")\"\NAK\f\STX")
+            ,(480,")\"\NAK\f\STX"),(481,")\"\NAK\f\STX"),(482,")\"\NAK\f\STX"),(483,")\"\NAK\f\STX"),(484,")\"\NAK\f\STX"),(485,")\"\NAK\f\STX"),(486,")\"\NAK\f\STX"),(487,")\"\NAK\f\STX"),(488,")\"\SYN\f\ETX"),(489,")\"\SYN\f\ETX")
+            ,(490,")\"\SYN\f\ETX"),(491,")\"\SYN\f\ETX"),(492,")\"\SYN\f\ETX"),(493,")\"\SYN\f\ETX"),(494,")\"\SYN\f\ETX"),(495,")\"\SYN\f\ETX"),(496,")\"\SYN\f\ETX"),(497,")\"\SYN\r\ETX"),(498,")\"\SYN\r\ETX"),(499,")\"\SYN\r\ETX")
+            ,(500,")\"\SYN\r\ETX"),(501,")\"\SYN\r\EOT"),(502,")\"\SYN\r\EOT"),(503,")\"\SYN\r\EOT"),(504,")\"\SYN\r\EOT"),(505,")\"\SYN\r\EOT"),(506,")\"\SYN\r\EOT"),(507,")\"\SYN\r\EOT"),(508,")\"\SYN\r\EOT"),(509,")\"\SYN\r\EOT")
+            ,(510,")\"\SYN\r\EOT"),(511,")\"\SYN\r\EOT"),(512,")\"\SYN\r\EOT"),(513,")\"\SYN\r\EOT"),(514,")\"\SYN\r\EOT"),(515,"*\"\SYN\r\ENQ"),(516,"*\"\SYN\r\ENQ"),(517,"*\"\SYN\r\ENQ"),(518,"*\"\SYN\r\ENQ"),(519,"*\"\SYN\SO\ENQ")
+            ,(520,"*\"\SYN\SO\ENQ"),(521,"*\"\SYN\SO\ENQ"),(522,"*\"\SYN\SO\ENQ"),(523,"*\"\SYN\SO\ENQ"),(524,"*\"\SYN\SO\ENQ"),(525,"*\"\SYN\SO\ENQ"),(526,"*\"\SYN\SO\ENQ"),(527,"*\"\SYN\SO\ENQ"),(528,"*\"\SYN\SO\ENQ"),(529,"*\"\SYN\SO\ENQ")
+            ,(530,"*\"\SYN\SO\ENQ"),(531,"*\"\SYN\SO\ACK"),(532,"*\"\SYN\SO\ACK"),(533,"*\"\SYN\SO\ACK"),(534,"*\"\SYN\SO\ACK"),(535,"*\"\SYN\SO\ACK"),(536,"*\"\SYN\SO\ACK"),(537,"*\"\SYN\SO\ACK"),(538,"*\"\SYN\SO\ACK"),(539,"*\"\SYN\SO\ACK")
+            ,(540,"*\"\SYN\SO\ACK"),(541,"*\"\SYN\SO\ACK"),(542,"*\"\SYN\SO\ACK"),(543,"*\"\SYN\SO\ACK"),(544,"*\"\SYN\SO\ACK"),(545,"*\"\SYN\SO\ACK"),(546,"*\"\SYN\SO\ACK"),(547,"*\"\SYN\SO\ACK"),(548,"*\"\SYN\SO\ACK"),(549,"*\"\SYN\SO\ACK")
+            ,(550,"*\"\SYN\SO\ACK\SOH"),(551,"*\"\SYN\SO\a\SOH"),(552,"*\"\SYN\SO\a\SOH"),(553,"*\"\SYN\SO\a\SOH"),(554,"*\"\SYN\SO\a\SOH"),(555,"*\"\SYN\SO\a\SOH"),(556,"*\"\SYN\SO\a\SOH"),(557,"*\"\SYN\SO\a\SOH"),(558,"*\"\SYN\SO\a\SOH"),(559,"*\"\SYN\SO\a\SOH")
+            ,(560,"*\"\SYN\SO\a\SOH"),(561,"*\"\SYN\SI\a\SOH"),(562,"*\"\SYN\SI\a\SOH"),(563,"*\"\SYN\SI\a\SOH"),(564,"*\"\SYN\SI\a\SOH"),(565,"*\"\SYN\SI\a\SOH"),(566,"*\"\SYN\SI\a\SOH"),(567,"*\"\SYN\SI\a\SOH"),(568,"*\"\SYN\SI\a\SOH"),(569,"*!\SYN\SI\a\SOH")
+            ,(570,"*!\SYN\SI\a\SOH"),(571,"*!\SYN\SI\a\SOH"),(572,"*!\SYN\SI\a\SOH"),(573,"*!\SYN\SI\a\SOH"),(574,"*!\SYN\SI\a\SOH"),(575,"*!\SYN\SI\a\SOH"),(576,"*!\SYN\SI\a\SOH"),(577,"*!\SYN\SI\b\SOH"),(578,"*!\SYN\SI\b\SOH"),(579,"*!\SYN\SI\b\SOH")
+            ,(580,"*!\SYN\SI\b\SOH"),(581,"*!\SYN\SI\b\SOH"),(582,"*!\SYN\SI\b\SOH"),(583,"*!\SYN\SI\b\SOH"),(584,"*!\SYN\SI\b\SOH"),(585,"*!\SYN\SI\b\SOH"),(586,"*!\SYN\SI\b\SOH"),(587,"*!\SYN\SI\b\SOH"),(588,"*!\SYN\SI\b\STX"),(589,"*!\SYN\SI\b\STX")
+            ,(590,"*!\SYN\SI\b\STX"),(591,"*!\SYN\SI\b\STX"),(592,"*!\SYN\SI\b\STX"),(593,"*!\SYN\SI\b\STX"),(594,"*!\SYN\SI\b\STX"),(595,"*!\SYN\SI\b\STX"),(596,"*!\SYN\SI\b\STX"),(597,"*!\SYN\SI\b\STX"),(598,"*!\SYN\SI\b\STX"),(599,"*!\SYN\SI\b\STX")
+            ,(600,"*!\SYN\SI\b\STX"),(601,"*!\SYN\SI\b\STX"),(602,"*!\SYN\SI\b\STX"),(603,"*!\SYN\SI\b\STX"),(604,"*!\SYN\SI\b\STX"),(605,"*!\SYN\SI\b\STX"),(606,"*!\SYN\SI\t\STX"),(607,"*!\SYN\SI\t\STX"),(608,"*!\SYN\SI\t\STX"),(609,"*!\SYN\SI\t\STX")
+            ,(610,"*!\SYN\SI\t\STX"),(611,"*!\SYN\SI\t\ETX"),(612,"*!\SYN\SI\t\ETX"),(613,"*!\SYN\SI\t\ETX"),(614,"*!\SYN\SI\t\ETX"),(615,"*!\SYN\SI\t\ETX"),(616,"*!\SYN\SI\t\ETX"),(617,"*!\SYN\SI\t\ETX"),(618,"*!\SYN\SI\t\ETX"),(619,"*!\SYN\SI\t\ETX")
+            ,(620,"*!\SYN\SI\t\ETX"),(621,"*!\SYN\SI\t\ETX"),(622,"*!\SYN\SI\t\ETX"),(623,"*!\SYN\SI\t\ETX"),(624,"*!\SYN\SI\t\ETX"),(625,"*!\SYN\SI\t\ETX"),(626,"*!\SYN\SI\t\ETX"),(627,"*!\SYN\SI\t\ETX"),(628,"*!\SYN\SI\t\ETX"),(629,"*!\SYN\SI\t\ETX")
+            ,(630,"*!\SYN\SI\t\ETX"),(631,"*!\SYN\SI\t\ETX"),(632,"*!\SYN\SI\t\ETX"),(633,"*!\SYN\SI\t\ETX"),(634,"*!\SYN\SI\t\EOT"),(635,"*!\SYN\SI\t\EOT"),(636,"*!\SYN\SI\t\EOT"),(637,"*!\SYN\SI\t\EOT"),(638,"*!\SYN\SI\t\EOT"),(639,"*!\SYN\DLE\t\EOT")
+            ,(640,"*!\SYN\DLE\n\EOT"),(641,"*!\SYN\DLE\n\EOT"),(642,"*!\SYN\DLE\n\EOT"),(643,"*!\SYN\DLE\n\EOT"),(644,"*!\SYN\DLE\n\EOT"),(645,"*!\SYN\DLE\n\EOT"),(646,"*!\SYN\DLE\n\EOT"),(647,"*!\SYN\DLE\n\EOT"),(648,"*!\SYN\DLE\n\EOT"),(649,"*!\SYN\DLE\n\EOT")
+            ,(650,"*!\SYN\DLE\n\EOT\SOH"),(651,"*!\SYN\DLE\n\EOT\SOH"),(652,"*!\SYN\DLE\n\EOT\SOH"),(653,"*!\SYN\DLE\n\EOT\SOH"),(654,"*!\SYN\DLE\n\EOT\SOH"),(655,"*!\SYN\DLE\n\EOT\SOH"),(656,"*!\SYN\DLE\n\EOT\SOH"),(657,"*!\SYN\DLE\n\EOT\SOH"),(658,"*!\SYN\DLE\n\EOT\SOH"),(659,"*!\SYN\DLE\n\EOT\SOH")
+            ,(660,"*!\SYN\DLE\n\EOT\SOH"),(661,"*!\SYN\DLE\n\EOT\SOH"),(662,"*!\SYN\DLE\n\EOT\SOH"),(663,"*!\SYN\DLE\n\ENQ\SOH"),(664,"*!\SYN\DLE\n\ENQ\SOH"),(665,"*!\SYN\DLE\n\ENQ\SOH"),(666,"*!\SYN\DLE\n\ENQ\SOH"),(667,"*!\SYN\DLE\n\ENQ\SOH"),(668,"*!\SYN\DLE\n\ENQ\SOH"),(669,"*!\SYN\DLE\n\ENQ\SOH")
+            ,(670,"*!\SYN\DLE\n\ENQ\SOH"),(671,"*!\SYN\DLE\n\ENQ\SOH"),(672,"* \SYN\DLE\n\ENQ\SOH"),(673,"* \SYN\DLE\n\ENQ\SOH"),(674,"* \SYN\DLE\n\ENQ\SOH"),(675,"* \SYN\DLE\n\ENQ\SOH"),(676,"* \SYN\DLE\n\ENQ\SOH"),(677,"* \SYN\DLE\n\ENQ\SOH"),(678,"* \SYN\DLE\n\ENQ\SOH"),(679,"* \SYN\DLE\n\ENQ\SOH")
+            ,(680,"* \SYN\DLE\n\ENQ\SOH"),(681,"* \SYN\DLE\n\ENQ\SOH"),(682,"* \SYN\DLE\n\ENQ\SOH"),(683,"* \SYN\DLE\n\ENQ\SOH"),(684,"* \SYN\DLE\n\ENQ\SOH"),(685,"* \SYN\DLE\n\ENQ\SOH"),(686,"* \SYN\DLE\n\ENQ\SOH"),(687,"* \SYN\DLE\n\ENQ\SOH"),(688,"* \SYN\DLE\n\ENQ\SOH"),(689,"* \SYN\DLE\n\ENQ\SOH")
+            ,(690,"* \SYN\DLE\n\ENQ\SOH"),(691,"* \SYN\DLE\n\ENQ\SOH"),(692,"* \SYN\DLE\n\ENQ\SOH"),(693,"* \SYN\DLE\n\ENQ\SOH"),(694,"* \SYN\DLE\n\ENQ\SOH"),(695,"* \SYN\DLE\n\ENQ\SOH"),(696,"* \SYN\DLE\n\ENQ\SOH"),(697,"* \SYN\DLE\n\ENQ\SOH"),(698,"* \SYN\DLE\n\ENQ\SOH"),(699,"* \SYN\DLE\n\ENQ\SOH")
+            ,(700,"* \SYN\DLE\n\ACK\SOH"),(701,"* \SYN\DLE\n\ACK\SOH"),(702,"* \SYN\DLE\n\ACK\SOH"),(703,"* \SYN\DLE\n\ACK\SOH"),(704,"* \SYN\DLE\n\ACK\SOH"),(705,"* \SYN\DLE\n\ACK\SOH"),(706,"* \SYN\DLE\n\ACK\SOH"),(707,"* \SYN\DLE\n\ACK\SOH"),(708,"* \SYN\DLE\n\ACK\SOH"),(709,"* \SYN\DLE\n\ACK\SOH")
+            ,(710,"* \SYN\DLE\n\ACK\SOH"),(711,"* \SYN\DLE\n\ACK\SOH"),(712,"* \SYN\DLE\n\ACK\SOH"),(713,"* \SYN\DLE\n\ACK\STX"),(714,"* \SYN\DLE\n\ACK\STX"),(715,"* \SYN\DLE\v\ACK\STX"),(716,"* \SYN\DLE\v\ACK\STX"),(717,"* \SYN\DLE\v\ACK\STX"),(718,"* \SYN\DLE\v\ACK\STX"),(719,"* \SYN\DLE\v\ACK\STX")
+            ,(720,"* \SYN\DLE\v\ACK\STX"),(721,"* \SYN\DLE\v\ACK\STX"),(722,"* \SYN\DLE\v\ACK\STX"),(723,"* \SYN\DLE\v\ACK\STX"),(724,"* \SYN\DLE\v\ACK\STX"),(725,"* \SYN\DLE\v\ACK\STX"),(726,"* \SYN\DLE\v\ACK\STX"),(727,"* \SYN\DLE\v\ACK\STX"),(728,"* \SYN\DLE\v\ACK\STX"),(729,"* \SYN\DLE\v\ACK\STX")
+            ,(730,"* \SYN\SI\v\ACK\STX"),(731,"* \SYN\SI\v\ACK\STX"),(732,"* \SYN\SI\v\ACK\STX"),(733,"* \SYN\SI\v\ACK\STX"),(734,"* \SYN\SI\v\ACK\STX"),(735,"* \SYN\SI\v\ACK\STX"),(736,"* \SYN\SI\v\ACK\STX"),(737,"* \SYN\SI\v\ACK\STX"),(738,"* \SYN\SI\v\ACK\STX"),(739,"* \SYN\SI\v\ACK\STX")
+            ,(740,"*\US\SYN\SI\v\ACK\STX"),(741,"*\US\SYN\SI\v\ACK\STX"),(742,"*\US\NAK\SI\v\ACK\STX"),(743,"*\US\NAK\SI\v\ACK\STX"),(744,"*\US\NAK\SI\v\ACK\STX"),(745,"*\US\NAK\SI\v\ACK\STX"),(746,"*\US\NAK\SI\v\ACK\STX"),(747,"*\US\NAK\SI\v\ACK\STX"),(748,"*\US\NAK\SI\v\a\STX"),(749,"*\US\NAK\SI\v\a\ETX")
+            ,(750,"*\US\NAK\SI\v\a\ETX"),(751,"*\US\NAK\SI\v\a\ETX\SOH"),(752,"*\US\NAK\SI\v\a\ETX\SOH"),(753,"*\US\NAK\SI\v\a\ETX\SOH"),(754,"*\US\NAK\SI\v\a\ETX\SOH"),(755,"*\US\NAK\SI\v\a\ETX\SOH"),(756,"*\US\NAK\SI\v\a\ETX\SOH"),(757,"*\US\NAK\SI\v\a\ETX\SOH"),(758,"*\US\NAK\SI\v\a\ETX\SOH"),(759,"*\US\NAK\SI\v\a\ETX\SOH")
+            ,(760,"*\US\NAK\SI\v\a\ETX\SOH"),(761,"*\US\NAK\SI\v\a\ETX\SOH"),(762,"*\US\NAK\SI\v\a\ETX\SOH"),(763,"*\US\NAK\SI\v\a\ETX\SOH"),(764,"*\US\NAK\SI\v\a\ETX\SOH"),(765,"*\US\NAK\SI\v\a\ETX\SOH"),(766,"*\US\NAK\SI\v\a\ETX\SOH"),(767,"*\US\NAK\SI\v\a\ETX\SOH"),(768,"*\US\NAK\SI\v\a\ETX\SOH"),(769,"*\US\NAK\SI\v\a\ETX\SOH")
+            ,(770,"*\US\NAK\SI\v\a\ETX\SOH"),(771,"*\US\NAK\SI\v\a\ETX\SOH"),(772,"*\US\NAK\SI\v\a\ETX\SOH"),(773,"*\US\NAK\SI\v\a\ETX\SOH"),(774,"*\US\NAK\SI\v\a\ETX\SOH"),(775,"*\US\NAK\SI\v\a\ETX\SOH"),(776,"*\US\NAK\SI\v\a\ETX\SOH"),(777,"*\US\NAK\SI\v\a\ETX\SOH"),(778,"*\US\NAK\SI\v\a\ETX\SOH"),(779,"*\US\NAK\SI\v\a\ETX\SOH")
+            ,(780,"*\US\NAK\SI\v\a\ETX\SOH"),(781,"*\US\NAK\SI\v\a\ETX\SOH"),(782,"*\US\NAK\SI\v\a\ETX\SOH"),(783,"*\US\NAK\SI\v\a\ETX\SOH"),(784,"*\US\NAK\SI\v\a\ETX\SOH"),(785,"*\US\NAK\SI\v\a\ETX\SOH"),(786,"*\US\NAK\SI\v\a\ETX\SOH"),(787,"*\US\NAK\SI\v\a\ETX\SOH"),(788,"*\US\NAK\SI\v\a\ETX\SOH"),(789,"*\US\NAK\SI\v\a\ETX\SOH")
+            ,(790,"*\US\NAK\SI\v\a\ETX\SOH"),(791,"*\US\NAK\SI\v\a\ETX\SOH"),(792,"*\US\NAK\SI\v\a\ETX\SOH"),(793,"*\US\NAK\SI\v\a\ETX\SOH"),(794,"*\US\NAK\SI\v\a\ETX\SOH"),(795,"*\US\NAK\SI\v\a\ETX\SOH"),(796,"*\US\NAK\SI\v\a\ETX\SOH"),(797,"*\US\NAK\SI\v\a\ETX\SOH"),(798,"*\US\NAK\SI\v\a\EOT\SOH"),(799,"*\RS\NAK\SI\v\a\EOT\SOH")
+            ,(800,"*\RS\NAK\SI\v\a\EOT\SOH"),(801,"*\RS\NAK\SI\v\a\EOT\SOH"),(802,"*\RS\NAK\SI\v\a\EOT\SOH"),(803,"*\RS\NAK\SI\v\a\EOT\SOH"),(804,"*\RS\NAK\SI\v\a\EOT\SOH"),(805,"*\RS\NAK\SI\v\a\EOT\SOH"),(806,"*\RS\NAK\SI\v\a\EOT\SOH"),(807,"*\RS\NAK\SI\v\a\EOT\SOH"),(808,"*\RS\NAK\SI\v\a\EOT\SOH"),(809,"*\RS\NAK\SI\v\a\EOT\SOH")
+            ,(810,"*\RS\NAK\SI\v\a\EOT\SOH"),(811,"*\RS\NAK\SI\v\a\EOT\SOH"),(812,"*\RS\NAK\SI\v\a\EOT\SOH"),(813,"*\RS\NAK\SI\v\a\EOT\SOH"),(814,"*\RS\NAK\SI\v\a\EOT\SOH"),(815,"*\RS\NAK\SI\v\a\EOT\SOH"),(816,"*\RS\NAK\SI\v\a\EOT\SOH"),(817,"*\RS\DC4\SI\v\a\EOT\SOH"),(818,"*\RS\DC4\SI\v\a\EOT\SOH"),(819,"*\RS\DC4\SI\v\a\EOT\SOH")
+            ,(820,"*\RS\DC4\SI\v\a\EOT\SOH"),(821,"*\RS\DC4\SI\v\a\EOT\SOH"),(822,"*\RS\DC4\SI\v\a\EOT\SOH"),(823,"*\RS\DC4\SI\v\a\EOT\SOH"),(824,"*\RS\DC4\SI\v\a\EOT\SOH"),(825,"*\RS\DC4\SI\v\a\EOT\SOH"),(826,"*\RS\DC4\SI\v\a\EOT\SOH"),(827,"*\RS\DC4\SI\v\a\EOT\SOH"),(828,"*\RS\DC4\SI\v\a\EOT\SOH"),(829,"*\RS\DC4\SI\v\a\EOT\SOH")
+            ,(830,"*\RS\DC4\SI\v\a\EOT\SOH"),(831,"*\RS\DC4\SI\v\a\EOT\SOH"),(832,"*\RS\DC4\SI\v\a\EOT\SOH"),(833,"*\RS\DC4\SI\v\a\EOT\SOH"),(834,"*\RS\DC4\SI\v\a\EOT\SOH"),(835,"*\RS\DC4\SI\v\a\EOT\SOH"),(836,"*\RS\DC4\SI\v\a\EOT\SOH"),(837,"*\RS\DC4\SI\v\a\EOT\SOH"),(838,"*\RS\DC4\SI\v\a\EOT\SOH"),(839,"*\RS\DC4\SI\v\a\EOT\SOH")
+            ,(840,"*\RS\DC4\SI\v\a\EOT\SOH"),(841,"*\RS\DC4\SI\v\a\EOT\SOH"),(842,"*\RS\DC4\SI\v\a\EOT\SOH"),(843,"*\RS\DC4\SI\v\a\EOT\SOH"),(844,"*\RS\DC4\SI\v\a\EOT\SOH"),(845,"*\RS\DC4\SI\v\a\EOT\SOH"),(846,"*\RS\DC4\SI\v\a\EOT\SOH"),(847,"*\RS\DC4\SI\v\a\EOT\SOH"),(848,"*\RS\DC4\SI\v\a\EOT\SOH"),(849,"*\RS\DC4\SI\v\a\EOT\SOH")
+            ,(850,"*\RS\DC4\SI\v\a\EOT\SOH\SOH"),(851,"*\RS\DC4\SO\v\a\EOT\SOH\SOH"),(852,"*\GS\DC4\SO\v\a\EOT\STX\SOH"),(853,"*\GS\DC4\SO\v\a\EOT\STX\SOH"),(854,"*\GS\DC4\SO\v\a\EOT\STX\SOH"),(855,"*\GS\DC4\SO\v\a\EOT\STX\SOH"),(856,"*\GS\DC4\SO\n\a\EOT\STX\SOH"),(857,"*\GS\DC4\SO\n\a\EOT\STX\SOH"),(858,"*\GS\DC4\SO\n\a\EOT\STX\SOH"),(859,"*\GS\DC4\SO\n\a\EOT\STX\SOH")
+            ,(860,"*\GS\DC4\SO\n\a\EOT\STX\SOH"),(861,"*\GS\DC4\SO\n\a\EOT\STX\SOH"),(862,"*\GS\DC4\SO\n\a\EOT\STX\SOH"),(863,"*\GS\DC4\SO\n\a\EOT\STX\SOH"),(864,"*\GS\DC4\SO\n\a\EOT\STX\SOH"),(865,"*\GS\DC4\SO\n\a\EOT\STX\SOH"),(866,"*\GS\DC4\SO\n\a\EOT\STX\SOH"),(867,"*\GS\DC4\SO\n\a\EOT\STX\SOH"),(868,"*\GS\DC4\SO\n\a\EOT\STX\SOH"),(869,"*\GS\DC4\SO\n\a\EOT\STX\SOH")
+            ,(870,"*\GS\DC4\SO\n\a\EOT\STX\SOH"),(871,"*\GS\DC4\SO\n\a\EOT\STX\SOH"),(872,"*\GS\DC4\SO\n\a\EOT\STX\SOH"),(873,"*\GS\DC4\SO\n\a\EOT\STX\SOH"),(874,"*\GS\DC4\SO\n\a\EOT\STX\SOH"),(875,"*\GS\DC4\SO\n\a\EOT\STX\SOH"),(876,"*\GS\DC4\SO\n\a\EOT\STX\SOH"),(877,"*\GS\DC4\SO\n\a\ENQ\STX\SOH"),(878,"*\GS\DC4\SO\n\a\ENQ\STX\SOH"),(879,"*\GS\DC4\SO\n\a\ENQ\STX\SOH")
+            ,(880,"*\GS\DC4\SO\n\a\ENQ\STX\SOH"),(881,"*\GS\DC4\SO\n\a\ENQ\STX\SOH"),(882,"*\GS\DC3\SO\n\a\ENQ\STX\SOH"),(883,"*\GS\DC3\SO\n\a\ENQ\STX\SOH"),(884,"*\GS\DC3\SO\n\a\ENQ\STX\SOH"),(885,"*\GS\DC3\SO\n\a\ENQ\STX\SOH"),(886,"*\GS\DC3\SO\n\a\ENQ\STX\SOH"),(887,"*\GS\DC3\SO\n\a\ENQ\STX\SOH"),(888,"*\GS\DC3\SO\n\a\ENQ\STX\SOH"),(889,"*\GS\DC3\SO\n\a\ENQ\STX\SOH")
+            ,(890,"*\GS\DC3\SO\n\a\ENQ\STX\SOH"),(891,"*\GS\DC3\SO\n\a\ENQ\STX\SOH"),(892,"*\GS\DC3\SO\n\a\ENQ\STX\SOH"),(893,"*\GS\DC3\SO\n\a\ENQ\STX\SOH"),(894,"*\GS\DC3\SO\n\a\ENQ\STX\SOH"),(895,"*\GS\DC3\SO\n\a\ENQ\STX\SOH"),(896,"*\GS\DC3\SO\n\a\ENQ\STX\SOH"),(897,"*\GS\DC3\SO\n\a\ENQ\STX\SOH"),(898,"*\GS\DC3\SO\n\a\ENQ\STX\SOH"),(899,"*\GS\DC3\SO\n\a\ENQ\STX\SOH")
+            ,(900,"*\GS\DC3\SO\n\a\ENQ\STX\SOH"),(901,"*\GS\DC3\SO\n\a\ENQ\STX\SOH"),(902,"*\GS\DC3\SO\n\a\ENQ\STX\SOH"),(903,"*\GS\DC3\SO\n\a\ENQ\STX\SOH"),(904,"*\GS\DC3\SO\n\a\ENQ\STX\SOH"),(905,"*\FS\DC3\SO\n\a\ENQ\STX\SOH"),(906,"*\FS\DC3\SO\n\a\ENQ\STX\SOH"),(907,"*\FS\DC3\SO\n\a\ENQ\STX\SOH"),(908,"*\FS\DC3\SO\n\a\ENQ\STX\SOH"),(909,"*\FS\DC3\SO\n\a\ENQ\STX\SOH")
+            ,(910,"*\FS\DC3\SO\n\a\ENQ\STX\SOH"),(911,"*\FS\DC3\SO\n\a\ENQ\STX\SOH"),(912,"*\FS\DC3\SO\n\a\ENQ\STX\SOH"),(913,"*\FS\DC3\SO\n\a\ENQ\STX\SOH"),(914,"*\FS\DC3\SO\n\a\ENQ\STX\SOH"),(915,"*\FS\DC3\SO\n\a\ENQ\STX\SOH"),(916,"*\FS\DC3\SO\n\a\ENQ\STX\SOH"),(917,"*\FS\DC3\SO\n\a\ENQ\STX\SOH"),(918,")\FS\DC3\SO\n\a\ENQ\STX\SOH"),(919,")\FS\DC3\SO\n\a\ENQ\STX\SOH")
+            ,(920,")\FS\DC3\SO\n\a\ENQ\STX\SOH"),(921,")\FS\DC3\SO\n\a\ENQ\STX\SOH"),(922,")\FS\DC3\SO\n\a\ENQ\STX\SOH"),(923,")\FS\DC3\SO\n\a\ENQ\STX\SOH"),(924,")\FS\DC3\SO\n\a\ENQ\STX\SOH"),(925,")\FS\DC3\SO\n\a\ENQ\STX\SOH"),(926,")\FS\DC3\SO\n\a\ENQ\STX\SOH"),(927,")\FS\DC3\SO\n\a\ENQ\STX\SOH"),(928,")\FS\DC3\SO\n\a\ENQ\STX\SOH"),(929,")\FS\DC3\r\n\a\ENQ\STX\SOH")
+            ,(930,")\FS\DC3\r\n\a\ENQ\STX\SOH"),(931,")\FS\DC3\r\n\a\ENQ\STX\SOH"),(932,")\FS\DC3\r\n\a\ENQ\STX\SOH"),(933,")\FS\DC3\r\n\a\ENQ\ETX\SOH"),(934,")\FS\DC3\r\n\a\ENQ\ETX\SOH"),(935,")\FS\DC3\r\n\a\ENQ\ETX\SOH"),(936,")\FS\DC3\r\n\a\ENQ\ETX\SOH"),(937,")\FS\DC3\r\n\a\ENQ\ETX\SOH"),(938,")\FS\DC3\r\n\a\ENQ\ETX\SOH"),(939,")\FS\DC3\r\n\a\ENQ\ETX\SOH")
+            ,(940,")\FS\DC2\r\n\a\ENQ\ETX\SOH"),(941,")\FS\DC2\r\n\a\ENQ\ETX\SOH"),(942,")\FS\DC2\r\n\a\ENQ\ETX\SOH"),(943,")\FS\DC2\r\n\a\ENQ\ETX\SOH"),(944,")\FS\DC2\r\n\a\ENQ\ETX\SOH"),(945,")\FS\DC2\r\n\a\ENQ\ETX\SOH"),(946,")\FS\DC2\r\n\a\ENQ\ETX\SOH"),(947,")\FS\DC2\r\n\a\ENQ\ETX\SOH"),(948,")\FS\DC2\r\n\a\ENQ\ETX\SOH"),(949,")\FS\DC2\r\n\a\ENQ\ETX\SOH")
+            ,(950,")\FS\DC2\r\n\a\ENQ\ETX\SOH\SOH"),(951,")\FS\DC2\r\n\a\ENQ\ETX\SOH\SOH"),(952,")\FS\DC2\r\n\a\ENQ\ETX\SOH\SOH"),(953,")\FS\DC2\r\n\a\ENQ\ETX\SOH\SOH"),(954,")\FS\DC2\r\n\a\ENQ\ETX\SOH\SOH"),(955,")\ESC\DC2\r\n\a\ENQ\ETX\SOH\SOH"),(956,")\ESC\DC2\r\n\a\ENQ\ETX\SOH\SOH"),(957,")\ESC\DC2\r\n\a\ENQ\ETX\SOH\SOH"),(958,")\ESC\DC2\r\n\a\ENQ\ETX\SOH\SOH"),(959,")\ESC\DC2\r\n\a\ENQ\ETX\SOH\SOH")
+            ,(960,")\ESC\DC2\r\n\a\ENQ\ETX\SOH\SOH"),(961,")\ESC\DC2\r\n\a\ENQ\ETX\SOH\SOH"),(962,")\ESC\DC2\r\n\a\ENQ\ETX\SOH\SOH"),(963,")\ESC\DC2\r\n\a\ENQ\ETX\SOH\SOH"),(964,")\ESC\DC2\r\n\a\ENQ\ETX\SOH\SOH"),(965,")\ESC\DC2\r\n\a\ENQ\ETX\SOH\SOH"),(966,")\ESC\DC2\r\n\a\ENQ\ETX\SOH\SOH"),(967,")\ESC\DC2\r\n\a\ENQ\ETX\SOH\SOH"),(968,")\ESC\DC2\r\n\a\ENQ\ETX\SOH\SOH"),(969,")\ESC\DC2\r\n\a\ENQ\ETX\SOH\SOH")
+            ,(970,")\ESC\DC2\r\n\a\ENQ\ETX\SOH\SOH"),(971,")\ESC\DC2\r\t\a\ENQ\ETX\SOH\SOH"),(972,")\ESC\DC2\r\t\a\ENQ\ETX\SOH\SOH"),(973,")\ESC\DC2\r\t\a\ENQ\ETX\SOH\SOH"),(974,")\ESC\DC2\r\t\a\ENQ\ETX\SOH\SOH"),(975,")\ESC\DC2\r\t\a\ENQ\ETX\SOH\SOH"),(976,")\ESC\DC2\r\t\a\ENQ\ETX\SOH\SOH"),(977,")\ESC\DC2\r\t\a\ENQ\ETX\SOH\SOH"),(978,")\ESC\DC2\r\t\a\ENQ\ETX\SOH\SOH"),(979,")\ESC\DC2\r\t\a\ENQ\ETX\SOH\SOH")
+            ,(980,")\ESC\DC2\r\t\a\ENQ\ETX\SOH\SOH"),(981,")\ESC\DC2\r\t\a\ENQ\ETX\SOH\SOH"),(982,")\ESC\DC2\r\t\a\ENQ\ETX\SOH\SOH"),(983,")\ESC\DC2\r\t\a\ENQ\ETX\SOH\SOH"),(984,")\ESC\DC2\r\t\a\ENQ\ETX\SOH\SOH"),(985,")\ESC\DC2\r\t\a\ENQ\ETX\SOH\SOH"),(986,")\ESC\DC2\r\t\a\ENQ\ETX\SOH\SOH"),(987,")\ESC\DC2\r\t\a\ENQ\ETX\SOH\SOH"),(988,")\ESC\DC2\r\t\a\ENQ\ETX\SOH\SOH"),(989,")\ESC\DC2\r\t\a\ENQ\ETX\SOH\SOH"),(991,")\ESC\DC2\r\t\a\ENQ\ETX\SOH\SOH"),(992,")\ESC\DC2\r\t\a\ENQ\ETX\SOH\SOH"),(993,")\ESC\DC2\r\t\a\ENQ\ETX\SOH\SOH"),(994,")\ESC\DC2\r\t\a\ENQ\ETX\SOH\SOH"),(995,")\ESC\DC2\r\t\a\ENQ\ETX\SOH\SOH"),(996,")\ESC\DC2\r\t\a\ENQ\ETX\SOH\SOH"),(997,")\ESC\DC2\r\t\a\ENQ\ETX\SOH\SOH"),(998,")\ESC\DC2\r\t\a\ENQ\ETX\SOH\SOH"),(999,")\ESC\DC2\r\t\a\ENQ\ETX\SOH\SOH")
+            ,(1000,")\ESC\DC1\r\t\a\ENQ\ETX\SOH\SOH"),(1001,")\ESC\DC1\r\t\a\ENQ\ETX\SOH\SOH"),(1002,")\ESC\DC1\f\t\a\ENQ\ETX\SOH\SOH"),(1003,")\ESC\DC1\f\t\a\ENQ\ETX\SOH\SOH"),(1004,")\ESC\DC1\f\t\a\ENQ\ETX\SOH\SOH"),(1005,")\ESC\DC1\f\t\a\ENQ\ETX\SOH\SOH"),(1006,")\ESC\DC1\f\t\a\ENQ\ETX\SOH\SOH"),(1007,")\SUB\DC1\f\t\a\ENQ\ETX\SOH\SOH"),(1008,")\SUB\DC1\f\t\a\ENQ\ETX\SOH\SOH"),(1009,")\SUB\DC1\f\t\a\ENQ\ETX\SOH\SOH")
+            ,(1010,")\SUB\DC1\f\t\a\ENQ\ETX\SOH\SOH"),(1011,")\SUB\DC1\f\t\a\ENQ\ETX\SOH\SOH"),(1012,")\SUB\DC1\f\t\a\ENQ\ETX\SOH\SOH"),(1013,")\SUB\DC1\f\t\a\ENQ\ETX\SOH\SOH"),(1014,")\SUB\DC1\f\t\a\ENQ\ETX\SOH\SOH"),(1015,")\SUB\DC1\f\t\a\ENQ\ETX\SOH\SOH"),(1016,")\SUB\DC1\f\t\a\ENQ\ETX\SOH\SOH"),(1017,")\SUB\DC1\f\t\a\ENQ\ETX\SOH\SOH"),(1018,")\SUB\DC1\f\t\a\ENQ\ETX\SOH\SOH"),(1019,")\SUB\DC1\f\t\a\ENQ\ETX\SOH\SOH"),(1021,")\SUB\DC1\f\t\a\ENQ\ETX\SOH\SOH"),(1022,")\SUB\DC1\f\t\a\ENQ\ETX\SOH\SOH"),(1024,")\SUB\DC1\f\t\a\ENQ\ETX\SOH\SOH"),(1025,")\SUB\DC1\f\t\a\ENQ\ETX\SOH\SOH"),(1026,")\SUB\DC1\f\t\a\ENQ\ETX\SOH\SOH"),(1028,")\SUB\DC1\f\t\ACK\ENQ\ETX\SOH\SOH"),(1029,")\SUB\DC1\f\t\ACK\ENQ\ETX\SOH\SOH"),(1031,")\SUB\DC1\f\t\ACK\ENQ\ETX\SOH\SOH"),(1033,")\SUB\DC1\f\t\ACK\ENQ\ETX\SOH\SOH"),(1034,")\SUB\DC1\f\t\ACK\ENQ\ETX\SOH\SOH"),(1035,")\SUB\DC1\f\t\ACK\ENQ\ETX\SOH\SOH"),(1037,")\SUB\DC1\f\t\ACK\ENQ\ETX\SOH\SOH"),(1038,")\SUB\DC1\f\t\ACK\ENQ\ETX\SOH\SOH"),(1039,")\SUB\DC1\f\t\ACK\ENQ\ETX\SOH\SOH")
+            ,(1040,")\SUB\DC1\f\t\ACK\ENQ\ETX\SOH\SOH"),(1041,")\SUB\DC1\f\t\ACK\ENQ\ETX\SOH\SOH"),(1042,")\SUB\DC1\f\t\ACK\ENQ\ETX\SOH\SOH"),(1043,")\SUB\DC1\f\t\ACK\ENQ\ETX\SOH\SOH"),(1044,")\SUB\DC1\f\t\ACK\ENQ\ETX\SOH\SOH"),(1045,")\SUB\DC1\f\t\ACK\ENQ\ETX\SOH\SOH"),(1046,")\SUB\DC1\f\t\ACK\ENQ\ETX\SOH\SOH"),(1047,")\SUB\DC1\f\t\ACK\EOT\ETX\SOH\SOH"),(1049,")\SUB\DC1\f\t\ACK\EOT\ETX\SOH\SOH"),(1051,")\SUB\DC1\f\t\ACK\EOT\ETX\SOH\SOH\SOH"),(1052,")\SUB\DC1\f\t\ACK\EOT\ETX\SOH\SOH\SOH"),(1053,")\SUB\DC1\f\t\ACK\EOT\ETX\SOH\SOH\SOH"),(1054,")\SUB\DC1\f\t\ACK\EOT\ETX\SOH\SOH\SOH"),(1055,")\SUB\DC1\f\t\ACK\EOT\ETX\SOH\SOH\SOH"),(1057,")\EM\DLE\f\b\ACK\EOT\ETX\SOH\SOH\SOH"),(1058,")\EM\DLE\f\b\ACK\EOT\ETX\SOH\SOH\SOH")
+            ,(1060,")\EM\DLE\f\b\ACK\EOT\ETX\SOH\SOH\SOH"),(1062,")\EM\DLE\f\b\ACK\EOT\ETX\STX\SOH\SOH"),(1063,")\EM\DLE\f\b\ACK\EOT\ETX\STX\SOH\SOH"),(1064,")\EM\DLE\f\b\ACK\EOT\ETX\STX\SOH\SOH"),(1065,")\EM\DLE\f\b\ACK\EOT\ETX\STX\SOH\SOH"),(1066,")\EM\DLE\f\b\ACK\EOT\ETX\STX\SOH\SOH"),(1067,")\EM\DLE\f\b\ACK\EOT\ETX\STX\SOH\SOH"),(1068,")\EM\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1069,")\EM\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH")
+            ,(1070,")\EM\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1072,")\EM\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1073,")\EM\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1075,")\EM\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1076,")\EM\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1078,")\EM\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1079,")\EM\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH")
+            ,(1080,")\EM\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1081,")\EM\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1082,")\EM\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1083,")\EM\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1084,")\EM\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1085,")\EM\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1086,")\EM\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1087,")\EM\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1088,")\EM\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1089,")\EM\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1091,")\EM\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1092,")\EM\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1094,")\EM\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1095,")\EM\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1096,")\EM\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1097,")\EM\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1098,")\EM\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1101,")\EM\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1102,")\EM\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1103,")\EM\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1105,")\EM\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1107,")\EM\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1108,")\EM\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1112,")\CAN\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1113,")\CAN\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1115,")\CAN\DLE\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1117,")\CAN\SI\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1119,")\CAN\SI\v\b\ACK\EOT\ETX\STX\SOH\SOH")
+            ,(1120,")\CAN\SI\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1125,")\CAN\SI\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1126,")\CAN\SI\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1127,")\CAN\SI\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1128,")\CAN\SI\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1129,")\CAN\SI\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1132,")\CAN\SI\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1133,")\CAN\SI\v\b\ACK\EOT\ETX\STX\SOH\SOH"),(1134,")\CAN\SI\v\b\ENQ\EOT\ETX\STX\SOH\SOH"),(1135,")\CAN\SI\v\b\ENQ\EOT\ETX\STX\SOH\SOH"),(1136,")\CAN\SI\v\b\ENQ\EOT\ETX\STX\SOH\SOH"),(1141,")\CAN\SI\n\a\ENQ\EOT\ETX\STX\SOH\SOH"),(1142,")\CAN\SI\n\a\ENQ\EOT\ETX\STX\SOH\SOH"),(1143,"(\CAN\SI\n\a\ENQ\EOT\ETX\STX\SOH\SOH"),(1144,"(\CAN\SI\n\a\ENQ\EOT\ETX\STX\SOH\SOH"),(1147,"(\CAN\SI\n\a\ENQ\EOT\ETX\STX\SOH\SOH"),(1152,"(\CAN\SI\n\a\ENQ\EOT\ETX\STX\SOH\SOH\SOH"),(1153,"(\CAN\SI\n\a\ENQ\EOT\ETX\STX\SOH\SOH\SOH"),(1154,"(\CAN\SI\n\a\ENQ\EOT\ETX\STX\SOH\SOH\SOH"),(1156,"(\CAN\SI\n\a\ENQ\EOT\ETX\STX\SOH\SOH\SOH"),(1157,"(\CAN\SI\n\a\ENQ\EOT\ETX\STX\SOH\SOH\SOH"),(1158,"(\CAN\SI\n\a\ENQ\EOT\ETX\STX\SOH\SOH\SOH"),(1159,"(\CAN\SI\n\a\ENQ\EOT\ETX\STX\SOH\SOH\SOH")
+            ,(1160,"(\CAN\SI\n\a\ENQ\EOT\ETX\STX\SOH\SOH\SOH"),(1165,"(\CAN\SI\n\a\ENQ\EOT\ETX\STX\SOH\SOH\SOH"),(1169,"(\ETB\SI\n\a\ENQ\EOT\ETX\STX\SOH\SOH\SOH"),(1171,"(\ETB\SI\n\a\ENQ\EOT\ETX\STX\SOH\SOH\SOH"),(1175,"(\ETB\SI\n\a\ENQ\EOT\ETX\STX\SOH\SOH\SOH"),(1177,"(\ETB\SI\n\a\ENQ\EOT\ETX\STX\SOH\SOH\SOH"),(1178,"(\ETB\SI\n\a\ENQ\EOT\ETX\STX\SOH\SOH\SOH")
+            ,(1180,"(\ETB\SO\n\a\ENQ\EOT\STX\STX\SOH\SOH\SOH"),(1181,"(\ETB\SO\n\a\ENQ\EOT\STX\STX\SOH\SOH\SOH"),(1183,"(\ETB\SO\n\a\ENQ\EOT\STX\STX\SOH\SOH\SOH"),(1185,"(\ETB\SO\n\a\ENQ\EOT\STX\STX\SOH\SOH\SOH"),(1195,"(\ETB\SO\n\a\ENQ\EOT\STX\STX\SOH\SOH\SOH"),(1198,"(\ETB\SO\n\a\ENQ\EOT\STX\STX\SOH\SOH\SOH"),(1201,"(\ETB\SO\n\a\ENQ\ETX\STX\SOH\SOH\SOH\SOH"),(1203,"(\ETB\SO\n\a\ENQ\ETX\STX\SOH\SOH\SOH\SOH"),(1205,"(\ETB\SO\n\a\ENQ\ETX\STX\SOH\SOH\SOH\SOH"),(1219,"(\ETB\SO\t\a\ENQ\ETX\STX\SOH\SOH\SOH\SOH"),(1225,"(\ETB\SO\t\ACK\ENQ\ETX\STX\SOH\SOH\SOH\SOH"),(1227,"(\ETB\SO\t\ACK\ENQ\ETX\STX\SOH\SOH\SOH\SOH"),(1238,"(\SYN\SO\t\ACK\ENQ\ETX\STX\SOH\SOH\SOH\SOH"),(1253,"(\SYN\r\t\ACK\EOT\ETX\STX\SOH\SOH\SOH\SOH\SOH"),(1262,"(\SYN\r\t\ACK\EOT\ETX\STX\SOH\SOH\SOH\SOH\SOH")
+            ,(1270,"(\SYN\r\t\ACK\EOT\ETX\STX\SOH\SOH\SOH\SOH\SOH")
+            ,(1280,"(\SYN\r\t\ACK\EOT\ETX\STX\SOH\SOH\SOH\SOH\SOH"),(1295,"(\NAK\r\b\ACK\EOT\ETX\STX\SOH\SOH\SOH\SOH\SOH"),(1321,"(\NAK\r\b\ACK\EOT\ETX\STX\SOH\SOH\SOH\SOH\SOH"),(1322,"(\NAK\r\b\ACK\EOT\ETX\STX\SOH\SOH\SOH\SOH\SOH")
+            ,(3100,"9\SO\a\ETX\SOH\SOH\SOH\SOH\SOH\SOH\SOH\SOH\SOH\SOH\SOH\SOH\SOH\SOH\SOH\SOH\SOH\SOH\SOH\SOH\SOH\SOH\SOH\SOH\SOH\SOH\SOH")]
diff --git a/src/Generations/GenBase.hs b/src/Generations/GenBase.hs
new file mode 100644
--- /dev/null
+++ b/src/Generations/GenBase.hs
@@ -0,0 +1,79 @@
+module Generations.GenBase ( Model, QualMethod
+                           , Generation(..), makeCommonHeader
+                           , qual_exact_fixed, qual_exact_decreasing
+                           , module Bio.Sequence.SFF
+                           , module Bio.Sequence.SFF_filters
+                           , module Statistics 
+                           , module HPLCount
+                           ) where
+
+import qualified Data.ByteString.Char8 as BC
+import Bio.Sequence.SFF
+import Bio.Sequence.SFF_filters
+
+import Debug.Trace (trace)
+
+import Statistics
+import HPLCount hiding (main)
+
+type Model = Int -> Distribution -- ^ each hpl length has its own distribution of flow values
+
+type QualMethod = HPLprob -> Model -> (Char,Flow) -> [Qual]
+
+data Generation = Gen {
+      name     :: String
+    , qcall    :: QualMethod -- ^ use the current model and hpl lenght to generate qual data
+    , models   :: [Model]  -- ^ a progression of initial models for the sequence of flows
+    , degrade  :: Distribution         -- the amount to increase a stdev multiplier each position
+    , disc_filters :: [DiscardFilter]
+    , trim_filters :: [TrimFilter]
+    -- stuff to build the commonheader from
+    , f_key :: String
+    , f_len   :: Int
+    , f_cycle :: String
+    --    readblock :: [ReadBlock] ?
+    }
+
+instance Show Generation where
+  show g = "Config:\n" ++ unlines (map ("  "++)
+           ["key: "++f_key g
+           ,"flowlength: "++show (f_len g), "flow cycle: "++show (f_cycle g)
+           ])
+--           ,"flow distributions:"])
+--           ++ unlines ["    "++show i++": "++show (model g i) | i <- [0..6]]
+
+-- | Calculate exact qualities from model using Bayes' theorem
+--   This should emulate Marguiles et al.'s method.  
+qual_exact_decreasing :: HPLprob -> Model -> (Char,Flow) -> [Qual]
+qual_exact_decreasing ft m (c,flow) = 
+  let f = fromIntegral flow / 100
+      prob hpl | hpl > 20  = error "can't handle hpls > 20" 
+               | otherwise = ft c hpl * pdf (m hpl) f / sum [pdf (m x) f * ft c x | x <- [0..20]]
+      probs = drop 1 $ scanl (+) 0 $ map prob [0..20]
+      quals = map (round . max 0 . min 60 . ((-10)*) . logBase 10) $ probs
+  in -- trace ("#"++show (c,flow) ++"\n"++show probs ++"\n"++show quals) $
+     take (fromIntegral $ (flow+50) `div` 100) $ quals
+     
+-- | Using Bayes, but only calculating the probablity of the call lenght
+--   being correct.  Should be similar to Titanium (but is it?)
+qual_exact_fixed :: HPLprob -> Model -> (Char,Flow) -> [Qual]
+qual_exact_fixed ft m (c,flow) = 
+  let f = fromIntegral flow / 100
+      hpl = fromIntegral $ (flow+50) `div` 100
+      prob = ft c hpl * pdf (m hpl) f / sum [pdf (m x) f * ft c x | x <- [0..20]]
+  in replicate hpl (round $ max 0 . min 60 $ (-10) * logBase 10 (1-prob))
+
+-- --------------------------------------------------
+-- Putting it together
+makeCommonHeader :: Generation -> CommonHeader
+makeCommonHeader g = CommonHeader
+    { index_offset = 0
+    , index_length = 0
+    , key_length = fromIntegral $ length $ f_key g
+    , flowgram_fmt = 1
+    , key = BC.pack $ f_key g
+
+    , num_reads = 0 -- fromIntegral $ n_reads g
+    , flow_length = fromIntegral $ f_len g
+    , flow = BC.pack $ concat $ replicate (f_len g `div` (length $ f_cycle g)) $ f_cycle g
+    }
diff --git a/src/Generations/Titanium.hs b/src/Generations/Titanium.hs
new file mode 100644
--- /dev/null
+++ b/src/Generations/Titanium.hs
@@ -0,0 +1,16 @@
+module Generations.Titanium where
+import Generations.GenBase
+
+titanium :: Generation
+titanium = Gen
+       { name     = "Titanium"
+       , qcall     = qual_exact_fixed
+       , models   = [\h -> let h' = fromIntegral h 
+                           in if h == 0 then LogNormal (negate 2.5) 0.2 else Normal h' (0.04+0.05*h')]
+       , degrade  = Normal 0.001 0.001
+       , disc_filters = [filter_key,filter_empty]
+       , trim_filters = []
+       , f_key        = "TCAG"
+       , f_len        = 800 -- :: Int16
+       , f_cycle      = "TACG"
+       }
diff --git a/src/HPLCount.hs b/src/HPLCount.hs
new file mode 100644
--- /dev/null
+++ b/src/HPLCount.hs
@@ -0,0 +1,44 @@
+-- count homopolymer distributions in a fasta file
+module HPLCount where
+
+import Bio.Sequence
+import qualified Data.ByteString.Lazy.Char8 as B
+import qualified Data.Map as M
+import Text.Printf
+import Data.Char (toUpper)
+import Data.List (intersperse)
+import Data.Maybe (fromJust)
+import System.Environment
+
+type HPLprob = Char -> Int -> Double
+
+-- lookup and return probability of this hpl length for this letter
+mkHPLprobs :: M.Map (Char,Int) Int -> HPLprob
+mkHPLprobs ft = let totals = [(c, fromIntegral $ sum [M.findWithDefault 0 (c,x) ft | x <- [0..50]]) | c <- "ACGT" ]
+                in \ch n -> fromIntegral (M.findWithDefault 0 (ch,n) ft) / fromJust (lookup ch totals)
+
+main = do
+  [f] <- getArgs
+  display "tacg" . freqtable . concatMap (hpls "tacg" . seqdata) =<< readFasta f
+
+display :: [Char] -> M.Map (Char,Int) Int -> IO ()
+display fs m = let imax = maximum $ map snd $ M.keys m
+                   header = concat ("len\t   " : intersperse "\t   " (map (return . toUpper) fs))
+               in putStrLn $ unlines (header : [ printf "%3d" i ++ concat [ printf "\t%5d" (M.findWithDefault 0 (c,i) m) |  c <- map toUpper fs ] | i <- [0..imax]])
+
+freqtable :: [(Char,Int)] -> M.Map (Char,Int) Int
+freqtable = go M.empty 
+  where
+    go m [] = m
+    go m (i:is) = let v = M.findWithDefault 0 i m 
+                      v' = v+1
+                      m' = M.insert i v' m
+                  in v' `seq` m' `seq` go m' is
+  
+hpls :: [Char] -> SeqData -> [(Char,Int)]
+hpls xs = go (cycle xs')
+  where xs' = map toUpper xs
+        go (f:fs) sd | B.null sd = []
+                     | not (elem (toUpper $ B.head sd) xs') = go (f:fs) (B.tail sd)
+                     | otherwise = let (this,rest) = B.span ((==f).toUpper) sd
+                                   in (f,fromIntegral (B.length this)) : go fs rest
diff --git a/src/Statistics.hs b/src/Statistics.hs
new file mode 100644
--- /dev/null
+++ b/src/Statistics.hs
@@ -0,0 +1,154 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+-- | Yet another simple module for implementing statistics stuff.
+module Statistics (sample, samples, normal, normals
+                  , stdnormal, stdnormals, Distribution(..), Prob(..)
+                  , pdf, pvalue, fromPdf, invcum, worsen
+                  , module Control.Monad.Random
+                  ) where
+
+import Control.Monad.Random
+import Data.Array.Unboxed
+
+foreign import ccall "erf" erf :: Double -> Double
+
+newtype Prob = P Double deriving Show
+
+instance Random Prob where
+    random g = let (a,g') = randomR (0,1) g in (P a,g')
+    randomR  = error "Specifying a range for a probability makes no sense."
+
+-- Todo: implement
+data Distribution = Normal Double Double     -- ^ mu and sigma
+                  | LogNormal Double Double  -- ^ mu and sigma
+                  | Uniform Double Double    -- ^ from/to inclusive
+                  | Empirical Double Double (UArray Int Double) 
+                    -- ^ Stores a cumulative distribution, centered on first 
+                    -- param (ref. 'worsen'), and second param is step size
+                  deriving (Show,Read)
+                  -- add more: StudentsT, SkewNormal, SkewT
+
+-- dummy to make deriving Read work
+instance Read (UArray i d) where
+
+-- | Build an empirical probablility distribution by mapping the given probabilities
+--   to uniformly spaced points starting at 'start' with 'step' points per unit.
+--   Automatically center on pvalue = 50.  
+fromPdf :: Double -> Double -> [Prob] -> Distribution
+fromPdf start h ps = let    ps' = acc 0 $ map ((/scale) . unprob) $ ps
+                            mu = start+(fromIntegral . length . takeWhile (<0.5)) ps'*h-h/2
+                            a = floor ((start-mu)/h)
+                            b = a+length ps'
+                            scale = sum [ x | P x <- ps]
+                            unprob (P x) = x
+                            acc _ [] = [1]
+                            acc c (x:xs) = let v = c+x
+                                           in if v >= 1 then [1] else v : acc v xs
+                        in Empirical mu h $ listArray (a,b) (0:ps')
+
+invcum :: Distribution -> Prob -> Double
+invcum (Normal mu sigma) (P z) = invcumnorm mu sigma z
+invcum (LogNormal mu sigma) (P z) = exp $ invcum (Normal mu sigma) (P z)
+invcum (Uniform a b) (P z) = a+(b-a)*z
+invcum (Empirical mu h cd) (P z) = let (a,b) = bounds cd in mu+bisect ((cd!).round) (fromIntegral a) (fromIntegral b) z * h
+
+
+-- | Calculate probability of sampling less than x
+--   (i.e. the cumulative distribution's value in x)
+pvalue :: Distribution -> Double -> Prob
+pvalue (Normal mu sigma) x = P (cumnorm mu sigma x)
+pvalue (Uniform a b) x | x <= a    = P 0 
+                       | x >= b    = P 1
+                       | otherwise = P ((x-a)/(b-a))
+pvalue (LogNormal mu sigma) x | x<1e-10   = P 0 -- not sufficient!
+                              | otherwise = P (cumlognorm mu sigma x)
+pvalue (Empirical mu h cd) x = let (a,b) = bounds cd
+                                   x' = (x-mu)/h
+                               in if x' < fromIntegral a then P 0
+                                  else if x' >= fromIntegral b then P 1
+                                    else let x1 = floor x'
+                                             x2 = x1+1
+                                             y1 = cd!x1
+                                             y2 = cd!x2
+                                         in P (y1 + (y2-y1)*(x'-fromIntegral x1))
+
+-- general functions for sampling
+
+sample :: RandomGen g => Distribution -> Rand g Double
+sample d = invcum d `fmap` getRandom
+
+-- sample (Uniform a b) = getRandomR (a,b)
+-- todo: replace with general function:
+samples  :: RandomGen g => Distribution -> Rand g [Double]
+samples (Normal mu sigma) = normals mu sigma
+samples (LogNormal mu sigma) = map exp `fmap` samples (Normal mu sigma)
+samples (Uniform a b) = getRandomRs (a,b)
+samples (Empirical _mu _h _cds) = error "todo: implement 'samples' for Empirical distributions"
+
+-- | The probability density function
+pdf :: Distribution -> Double -> Double -- Prob?
+pdf (Normal mu sigma) x = exp(negate(square (x-mu)/(2*square sigma)))/(sigma*sqrt(2*pi))
+pdf (LogNormal mu sigma) x
+    | x>0 = exp(negate(square (log x-mu)/(2*square sigma)))/(x*sigma*sqrt(2*pi))
+    | otherwise = 0
+pdf (Uniform a b) x
+    | x<b && x>= a = 1/(b-a)  -- interval is open on the right, to work correctly with empirical below
+    | otherwise = 0
+pdf (Empirical mu h cd) x = let (a,b) = bounds cd
+                                x' = (x-mu)/h
+                            in if x' < fromIntegral a then 0
+                               else if x' >= fromIntegral b then 0
+                                 else let x1 = floor x'
+                                          x2 = x1+1
+                                          y1 = cd!x1
+                                          y2 = cd!x2
+                                      in (y2-y1)/h
+-- ------------------------------
+-- Specifics
+-- ------------------------------
+square :: Double -> Double
+square x = x * x
+
+stdnormal :: RandomGen g => Rand g Double
+stdnormal = normal 0 1
+
+stdnormals :: RandomGen g => Rand g [Double]
+stdnormals = normals 0 1
+
+normal :: RandomGen g => Double -> Double -> Rand g Double
+normal mu sigma = do x <- getRandomR (0,1)
+                     return (invcumnorm mu sigma x)
+
+normals :: RandomGen g => Double -> Double -> Rand g [Double]
+normals mu sigma = do x <- normal mu sigma
+                      xs <- normals mu sigma
+                      return (x : xs)
+
+-- support
+invcumnorm :: Double -> Double -> Double -> Double
+invcumnorm mu sigma z = mu + bisect (cumnorm 0 sigma) (-limit*sigma) (limit*sigma) z
+
+bisect :: (Double -> Double) -> Double -> Double -> Double -> Double
+bisect f a b z = let c = (a+b)/2
+                     cn = f c
+                 in if abs (z - cn) < 10*epsilon || abs (a-b) < epsilon then c
+                    else if cn > z then bisect f a c z
+                         else bisect f c b z
+
+cumnorm :: Double -> Double -> Double -> Double
+cumnorm mu sigma x = 0.5*(1+erf((x-mu)/(sigma*sqrt 2)))
+
+cumlognorm :: Double -> Double -> Double -> Double
+cumlognorm mu sigma x = 0.5+0.5*erf ((log x-mu)/(sigma*sqrt 2))
+
+epsilon, limit :: Double
+epsilon = 0.0000000001
+limit = 4.4
+
+-- | Make a distribution wider by expanding (or contracting, if less than 1) 
+--   its stdev by some factor
+worsen :: Double -> Distribution -> Distribution
+worsen d (Normal mu sigma) = Normal mu (sigma*d)
+worsen d (LogNormal mu sigma) = LogNormal mu (sigma*d)
+worsen d (Uniform a b) = Uniform (a*(1-d)) (b*d) -- assumption alert?
+worsen d (Empirical mu h ds) = Empirical mu (h*d) ds
