packages feed

samtools-conduit-0.1.1.0: test/SamtoolsConduitCopy.hs

{-# LANGUAGE ScopedTypeVariables, OverloadedStrings #-}
module Main
       where

import Control.Monad.IO.Class
import Control.Monad.Trans.Resource
import qualified Data.ByteString.Char8 as BS
import qualified Data.Conduit as C
import qualified Data.Conduit.List as C
import Data.Maybe
import Numeric
import System.Environment
import System.FilePath
import System.IO

import qualified Bio.SamTools.Bam as Bam
import qualified Bio.SamTools.Conduit as Bam

main :: IO ()
main = getArgs >>= runWithArgs
  where runWithArgs [ inname ] = copy inname
        runWithArgs _ = do hPutStrLn stderr $ "Specify exactly one input BAM file"

copy :: FilePath -> IO ()
copy infile = do Bam.withBamInFile infile $ \hin ->
                   Bam.withBamOutFile (outfile "-1") (Bam.inHeader hin) $ \hout ->
                   runResourceT $ Bam.sourceHandle hin C.$$ Bam.sinkHandle hout
                 runResourceT $ Bam.sourceBamInFile infile C.$= process C.$$ Bam.sinkBamOutFile (outfile "-2")
                 runResourceT $ Bam.sourceBamInFile infile C.$= enumerate C.$$ Bam.sinkBamOutFile (outfile "-3")
  where outfile suffix = (takeBaseName infile) ++ suffix ++ (takeExtension infile)
                 
process :: (MonadIO m) => C.Conduit Bam.Bam1 m Bam.Bam1
process = C.mapM procOne
  where procOne b0 = let qyseq = fromMaybe "" . Bam.querySeq $ b0
                         nt = BS.foldl' (\n ch -> if ch == 'T' then n+1 else n) 0 qyseq
                         nn = BS.length qyseq
                         fstr = showFFloat (Just 3) ((fromIntegral nt / fromIntegral nn) :: Double) ""
                     in liftIO (Bam.addAuxZ b0 "XX" fstr)

enumerate :: (MonadIO m) => C.Conduit Bam.Bam1 m Bam.Bam1
enumerate = C.mapAccumM procOne 0 >> return ()
  where procOne b0 i = do b' <- liftIO $! Bam.addAuxi b0 "XY" i
                          return (i + 1, b')