sequence-formats 1.8.1.1 → 1.9.0.0
raw patch · 7 files changed
+213/−142 lines, 7 filesdep +streaming-commonsdep ~attoparsecdep ~basedep ~bytestringPVP ok
version bump matches the API change (PVP)
Dependencies added: streaming-commons
Dependency ranges changed: attoparsec, base, bytestring, containers, errors, exceptions, foldl, hspec, lens-family, pipes, pipes-attoparsec, pipes-bytestring, pipes-safe, pipes-zlib, tasty, tasty-hunit, transformers, vector
API changes (from Hackage documentation)
+ SequenceFormats.Utils: data () => Deflate
+ SequenceFormats.Utils: gzipConsumer :: MonadIO m => Deflate -> Handle -> Consumer ByteString m ()
+ SequenceFormats.Utils: writeFromPopper :: MonadIO m => Popper -> Handle -> m ()
- SequenceFormats.Eigenstrat: writeEigenstrat :: MonadSafe m => FilePath -> FilePath -> FilePath -> [EigenstratIndEntry] -> Consumer (EigenstratSnpEntry, GenoLine) m ()
+ SequenceFormats.Eigenstrat: writeEigenstrat :: MonadSafe m => FilePath -> FilePath -> FilePath -> [EigenstratIndEntry] -> Producer (EigenstratSnpEntry, GenoLine) m () -> m ()
- SequenceFormats.Eigenstrat: writeEigenstratGeno :: MonadIO m => Handle -> Consumer GenoLine m ()
+ SequenceFormats.Eigenstrat: writeEigenstratGeno :: MonadIO m => Maybe Deflate -> Handle -> Consumer GenoLine m ()
- SequenceFormats.Eigenstrat: writeEigenstratSnp :: MonadIO m => Handle -> Consumer EigenstratSnpEntry m ()
+ SequenceFormats.Eigenstrat: writeEigenstratSnp :: MonadIO m => Maybe Deflate -> Handle -> Consumer EigenstratSnpEntry m ()
- SequenceFormats.Plink: writeBim :: MonadIO m => Handle -> Consumer EigenstratSnpEntry m ()
+ SequenceFormats.Plink: writeBim :: MonadIO m => Maybe Deflate -> Handle -> Consumer EigenstratSnpEntry m ()
- SequenceFormats.Plink: writePlink :: MonadSafe m => FilePath -> FilePath -> FilePath -> [PlinkFamEntry] -> Consumer (EigenstratSnpEntry, GenoLine) m ()
+ SequenceFormats.Plink: writePlink :: MonadSafe m => FilePath -> FilePath -> FilePath -> [PlinkFamEntry] -> Producer (EigenstratSnpEntry, GenoLine) m () -> m ()
Files
- Changelog.md +1/−0
- sequence-formats.cabal +66/−97
- src/SequenceFormats/Eigenstrat.hs +38/−15
- src/SequenceFormats/Plink.hs +44/−17
- src/SequenceFormats/Utils.hs +25/−6
- test/SequenceFormats/EigenstratSpec.hs +20/−4
- test/SequenceFormats/PlinkSpec.hs +19/−3
Changelog.md view
@@ -1,5 +1,6 @@ # Changelog +- V 1.9.0.0: Added gzip-writing support for Eigenstrat and Plink files. This required a breaking change in `writeEigenstrat` and `writePlink`. - V 1.8.1.0: Added gzip-support (read-only for now) for Plink (bed and bim files) and VCF. - V 1.8.0.1: Allow reading arbitrary letters as reference base in Pileup format. Before only ACTG, N and M were allowed. Now all letters are allowed, as we found out that reference fasta files can contain more letters than just those and we
sequence-formats.cabal view
@@ -1,100 +1,69 @@-cabal-version: >=1.10-name: sequence-formats-version: 1.8.1.1-license: GPL-3-license-file: LICENSE-maintainer: stephan.schiffels@mac.com-author: Stephan Schiffels-homepage: https://github.com/stschiff/sequence-formats-bug-reports: https://github.com/stschiff/sequence-formats/issues-synopsis:- A package with basic parsing utilities for several Bioinformatic data formats.--description:- Contains utilities to parse and write Eigenstrat, Fasta, FreqSum, VCF, Plink and other file formats used in population genetics analyses.--category: Bioinformatics-build-type: Simple-extra-source-files:- README.md- Changelog.md- testDat/example.bed- testDat/example.eigenstratgeno- testDat/example.eigenstratgeno.gz- testDat/example.fam- testDat/example.fasta- testDat/example.freqsum- testDat/example.histogram.txt- testDat/example.ind- testDat/example.pileup- testDat/example.plink.bed- testDat/example.plink.bed.gz- testDat/example.plink.bim- testDat/example.plink.bim.gz- testDat/example.plink.fam- testDat/example.snp- testDat/example.snp.gz- testDat/example.vcf- testDat/example.vcf.gz+name: sequence-formats+version: 1.9.0.0+synopsis: A package with basic parsing utilities for several Bioinformatic data formats.+description: Contains utilities to parse and write Eigenstrat, Fasta, FreqSum, VCF, Plink and other file formats used in population genetics analyses.+license: GPL-3+license-file: LICENSE+author: Stephan Schiffels+maintainer: stephan.schiffels@mac.com+category: Bioinformatics+build-type: Simple+cabal-version: >=1.10+Homepage: https://github.com/stschiff/sequence-formats+Bug-Reports: https://github.com/stschiff/sequence-formats/issues +extra-source-files: README.md,+ Changelog.md,+ testDat/example.bed,+ testDat/example.eigenstratgeno,+ testDat/example.eigenstratgeno.gz,+ testDat/example.fam,+ testDat/example.fasta,+ testDat/example.freqsum,+ testDat/example.histogram.txt,+ testDat/example.ind,+ testDat/example.pileup,+ testDat/example.plink.bed,+ testDat/example.plink.bed.gz,+ testDat/example.plink.bim,+ testDat/example.plink.bim.gz,+ testDat/example.plink.fam+ testDat/example.snp,+ testDat/example.snp.gz,+ testDat/example.vcf,+ testDat/example.vcf.gz+ library- exposed-modules:- SequenceFormats.RareAlleleHistogram- SequenceFormats.FreqSum- SequenceFormats.Fasta- SequenceFormats.VCF- SequenceFormats.Eigenstrat- SequenceFormats.Plink- SequenceFormats.Utils- SequenceFormats.Pileup- SequenceFormats.Bed- SequenceFormats.Genomic-- hs-source-dirs: src- default-language: Haskell2010- build-depends:- base >=4.7 && <5,- containers >=0.6.7,- errors >=2.3.0,- attoparsec >=0.14.4,- pipes >=4.3.16,- transformers >=0.5.6.2,- bytestring >=0.11.5.2,- lens-family >=2.1.2,- pipes-bytestring >=2.1.7,- foldl >=1.4.15,- exceptions >=0.10.5,- pipes-safe >=2.3.4,- pipes-attoparsec >=0.6.0,- vector >=0.13.1.0,- pipes-zlib >=0.4.4.2--test-suite sequenceFormatTests- type: exitcode-stdio-1.0- main-is: Spec.hs- hs-source-dirs: test- other-modules:- SequenceFormats.EigenstratSpec- SequenceFormats.BedSpec- SequenceFormats.FastaSpec- SequenceFormats.FreqSumSpec- SequenceFormats.RareAlleleHistogramSpec- SequenceFormats.UtilsSpec- SequenceFormats.PlinkSpec- SequenceFormats.VCFSpec- SequenceFormats.PileupSpec+ exposed-modules: SequenceFormats.RareAlleleHistogram,+ SequenceFormats.FreqSum,+ SequenceFormats.Fasta,+ SequenceFormats.VCF,+ SequenceFormats.Eigenstrat,+ SequenceFormats.Plink,+ SequenceFormats.Utils,+ SequenceFormats.Pileup,+ SequenceFormats.Bed,+ SequenceFormats.Genomic+ hs-source-dirs: src+ build-depends: base >= 4.7 && < 5, containers, errors, attoparsec, pipes,+ transformers, bytestring, lens-family,+ pipes-bytestring, foldl, exceptions, pipes-safe,+ pipes-attoparsec, vector, pipes-zlib, streaming-commons+ default-language: Haskell2010 - default-language: Haskell2010- build-depends:- base >=4.17.2.0,- sequence-formats,- foldl >=1.4.15,- pipes >=4.3.16,- pipes-safe >=2.3.4,- tasty >=1.4.3,- vector >=0.13.1.0,- transformers >=0.5.6.2,- tasty-hunit >=0.10.1,- bytestring >=0.11.5.2,- containers >=0.6.7,- hspec >=2.10.10+Test-Suite sequenceFormatTests+ type: exitcode-stdio-1.0+ main-is: Spec.hs+ hs-source-dirs: test+ build-depends: base, sequence-formats, foldl, pipes, pipes-safe, tasty, vector,+ transformers, tasty-hunit, bytestring, containers, hspec, pipes-zlib+ other-modules: SequenceFormats.EigenstratSpec,+ SequenceFormats.BedSpec,+ SequenceFormats.FastaSpec,+ SequenceFormats.FreqSumSpec,+ SequenceFormats.RareAlleleHistogramSpec,+ SequenceFormats.UtilsSpec,+ SequenceFormats.PlinkSpec,+ SequenceFormats.VCFSpec,+ SequenceFormats.PileupSpec+ default-language: Haskell2010
src/SequenceFormats/Eigenstrat.hs view
@@ -14,7 +14,7 @@ SeqFormatException (..), consumeProducer, readFileProdCheckCompress,- word)+ word, gzipConsumer, writeFromPopper) import Control.Applicative ((<|>)) import Control.Exception (throw)@@ -23,9 +23,11 @@ import Control.Monad.IO.Class (MonadIO, liftIO) import qualified Data.Attoparsec.ByteString.Char8 as A import qualified Data.ByteString.Char8 as B+import Data.List (isSuffixOf)+import qualified Data.Streaming.Zlib as Z import Data.Vector (Vector, fromList, toList) import Pipes (Consumer, Pipe, Producer,- cat, for, yield, (>->))+ cat, for, yield, (>->), runEffect) import qualified Pipes.ByteString as PB import qualified Pipes.Prelude as P import Pipes.Safe (MonadSafe)@@ -162,10 +164,13 @@ Unknown -> "U" -- |Function to write an Eigenstrat Snp File. Returns a consumer expecting EigenstratSnpEntries.-writeEigenstratSnp :: (MonadIO m) => Handle -- ^The Eigenstrat Snp File Handle.+writeEigenstratSnp :: (MonadIO m) => Maybe Z.Deflate -- ^If Nothing, then no compression+ -> Handle -- ^The Eigenstrat Snp File Handle. -> Consumer EigenstratSnpEntry m () -- ^A consumer to read EigenstratSnpEntries-writeEigenstratSnp snpFileH =- let snpOutTextConsumer = PB.toHandle snpFileH+writeEigenstratSnp maybeDeflate snpFileH =+ let snpOutTextConsumer = case maybeDeflate of+ Nothing -> PB.toHandle snpFileH+ Just def -> gzipConsumer def snpFileH toTextPipe = P.map (\(EigenstratSnpEntry chrom pos gpos gid ref alt) -> let snpLine = B.intercalate "\t" [gid, unChrom chrom, B.pack (show gpos), B.pack (show pos), B.singleton ref, B.singleton alt]@@ -173,10 +178,13 @@ in toTextPipe >-> snpOutTextConsumer -- |Function to write an Eigentrat Geno File. Returns a consumer expecting Eigenstrat Genolines.-writeEigenstratGeno :: (MonadIO m) => Handle -- ^The Genotype file handle- -> Consumer GenoLine m () -- ^A consumer to read Genotype entries.-writeEigenstratGeno genoFileH =- let genoOutTextConsumer = PB.toHandle genoFileH+writeEigenstratGeno :: (MonadIO m) => Maybe Z.Deflate -- ^If Nothing, then no compression+ -> Handle -- ^The Genotype file handle+ -> Consumer GenoLine m () -- ^A consumer to read Genotype entries.+writeEigenstratGeno maybeDeflate genoFileH =+ let genoOutTextConsumer = case maybeDeflate of+ Nothing -> PB.toHandle genoFileH+ Just def -> gzipConsumer def genoFileH toTextPipe = P.map (\genoLine -> let genoLineStr = B.concat . map (B.pack . show . toEigenStratNum) . toList $ genoLine in genoLineStr <> "\n")@@ -193,10 +201,25 @@ -> FilePath -- ^The Snp File -> FilePath -- ^The Ind file -> [EigenstratIndEntry] -- ^The list of individual entries- -> Consumer (EigenstratSnpEntry, GenoLine) m () -- ^A consumer to read joint Snp/Genotype entries.-writeEigenstrat genoFile snpFile indFile indEntries = do+ -> Producer (EigenstratSnpEntry, GenoLine) m () -- ^A consumer to read joint Snp/Genotype entries.+ -> m ()+writeEigenstrat genoFile snpFile indFile indEntries prod = do+ snpDeflate <- if ".gz" `isSuffixOf` snpFile then fmap Just . liftIO $ Z.initDeflate 6 (Z.WindowBits 31) else return Nothing+ genoDeflate <- if ".gz" `isSuffixOf` genoFile then fmap Just . liftIO $ Z.initDeflate 6 (Z.WindowBits 31) else return Nothing liftIO $ writeEigenstratIndFile indFile indEntries- let snpOutConsumer = PS.withFile snpFile WriteMode writeEigenstratSnp- genoOutConsumer = PS.withFile genoFile WriteMode writeEigenstratGeno- P.tee (P.map fst >-> snpOutConsumer) >-> P.map snd >-> genoOutConsumer-+ (_, snpFileH) <- PS.openFile snpFile WriteMode+ (_, genoFileH) <- PS.openFile genoFile WriteMode+ let snpOutConsumer = writeEigenstratSnp snpDeflate snpFileH+ genoOutConsumer = writeEigenstratGeno genoDeflate genoFileH+ runEffect $ prod >-> P.tee (P.map fst >-> snpOutConsumer) >-> P.map snd >-> genoOutConsumer+ case snpDeflate of+ Nothing -> return ()+ Just def -> do+ let finalPop = Z.finishDeflate def+ writeFromPopper finalPop snpFileH+ case genoDeflate of+ Nothing -> return ()+ Just def -> do+ let finalPop = Z.finishDeflate def+ writeFromPopper finalPop genoFileH+
src/SequenceFormats/Plink.hs view
@@ -18,7 +18,7 @@ Sex (..)) import SequenceFormats.Utils (Chrom (..), consumeProducer, readFileProdCheckCompress,- word)+ word, gzipConsumer, writeFromPopper) import Control.Applicative ((<|>)) import Control.Monad (forM_, void)@@ -30,10 +30,11 @@ import Data.Bits (shiftL, shiftR, (.&.), (.|.)) import qualified Data.ByteString as BB import qualified Data.ByteString.Char8 as B-import Data.List (intercalate)+import Data.List (intercalate, isSuffixOf)+import qualified Data.Streaming.Zlib as Z import Data.Vector (fromList, toList) import Data.Word (Word8)-import Pipes (Consumer, Producer, (>->))+import Pipes (Consumer, Producer, (>->), runEffect) import Pipes.Attoparsec (ParsingError (..), parse) import qualified Pipes.ByteString as PB import qualified Pipes.Prelude as P@@ -167,10 +168,13 @@ return (indEntries, P.zip snpProd genoProd) -- |Function to write a Bim file. Returns a consumer expecting EigenstratSnpEntries.-writeBim :: (MonadIO m) => Handle -- ^The Eigenstrat Snp File handle.+writeBim :: (MonadIO m) => Maybe Z.Deflate -- ^If Nothing, then no Compression+ -> Handle -- ^The Eigenstrat Snp File handle. -> Consumer EigenstratSnpEntry m () -- ^A consumer to read EigenstratSnpEntries-writeBim snpFileH =- let snpOutTextConsumer = PB.toHandle snpFileH+writeBim maybeDeflate snpFileH =+ let snpOutTextConsumer = case maybeDeflate of+ Nothing -> PB.toHandle snpFileH+ Just def -> gzipConsumer def snpFileH toTextPipe = P.map (\(EigenstratSnpEntry chrom pos gpos gid ref alt) -> let bimLine = B.intercalate "\t" [unChrom chrom, gid, B.pack (show gpos), B.pack (show pos), B.singleton ref, B.singleton alt]@@ -190,12 +194,20 @@ Unknown -> "0" -- |Function to write an Eigentrat Geno File. Returns a consumer expecting Eigenstrat Genolines.-writeBed :: (MonadIO m) => Handle -- ^The Bed file handle- -> Consumer GenoLine m () -- ^A consumer to read Genotype entries.-writeBed bedFileH = do- liftIO $ BB.hPut bedFileH (BB.pack [0b01101100, 0b00011011, 0b00000001])- let bedOutConsumer = PB.toHandle bedFileH- toPlinkPipe = P.map (BB.pack . genoLineToBytes)+writeBed :: (MonadIO m) => Maybe Z.Deflate -- ^If Nothing, then no Compression+ -> Handle -- ^The Bed file handle+ -> Consumer GenoLine m () -- ^A consumer to read Genotype entries.+writeBed maybeDeflate bedFileH = do+ let stickyBytes = BB.pack [0b01101100, 0b00011011, 0b00000001]+ bedOutConsumer <- case maybeDeflate of+ Nothing -> do+ liftIO $ BB.hPut bedFileH stickyBytes+ return $ PB.toHandle bedFileH+ Just def -> do+ pop <- liftIO (Z.feedDeflate def stickyBytes)+ liftIO (writeFromPopper pop bedFileH)+ return $ gzipConsumer def bedFileH+ let toPlinkPipe = P.map (BB.pack . genoLineToBytes) toPlinkPipe >-> bedOutConsumer where genoLineToBytes :: GenoLine -> [Word8]@@ -221,9 +233,24 @@ -> FilePath -- ^The Bim File -> FilePath -- ^The Fam file -> [PlinkFamEntry] -- ^The list of individual entries- -> Consumer (EigenstratSnpEntry, GenoLine) m () -- ^A consumer to read joint Snp/Genotype entries.-writePlink bedFile bimFile famFile indEntries = do+ -> Producer (EigenstratSnpEntry, GenoLine) m () -- ^A consumer to read joint Snp/Genotype entries.+ -> m ()+writePlink bedFile bimFile famFile indEntries prod = do+ bimDeflate <- if ".gz" `isSuffixOf` bimFile then fmap Just . liftIO $ Z.initDeflate 6 (Z.WindowBits 31) else return Nothing+ bedDeflate <- if ".gz" `isSuffixOf` bedFile then fmap Just . liftIO $ Z.initDeflate 6 (Z.WindowBits 31) else return Nothing liftIO $ writeFam famFile indEntries- let bimOutConsumer = PS.withFile bimFile WriteMode writeBim- bedOutConsumer = PS.withFile bedFile WriteMode writeBed- P.tee (P.map fst >-> bimOutConsumer) >-> P.map snd >-> bedOutConsumer+ (_, bimFileH) <- PS.openFile bimFile WriteMode+ (_, bedFileH) <- PS.openFile bedFile WriteMode+ let bimOutConsumer = writeBim bimDeflate bimFileH+ bedOutConsumer = writeBed bedDeflate bedFileH+ runEffect $ prod >-> P.tee (P.map fst >-> bimOutConsumer) >-> P.map snd >-> bedOutConsumer+ case bimDeflate of+ Nothing -> return ()+ Just def -> do+ let finalPop = Z.finishDeflate def+ writeFromPopper finalPop bimFileH+ case bedDeflate of+ Nothing -> return ()+ Just def -> do+ let finalPop = Z.finishDeflate def+ writeFromPopper finalPop bedFileH
src/SequenceFormats/Utils.hs view
@@ -5,23 +5,25 @@ module SequenceFormats.Utils (liftParsingErrors, consumeProducer, readFileProd, readFileProdCheckCompress, SeqFormatException(..),- Chrom(..), word) where+ Chrom(..), word, gzipConsumer, writeFromPopper, Z.Deflate) where import Control.Error (readErr)-import Control.Exception (Exception, throw)+import Control.Exception (Exception, throw, throwIO) import Control.Monad.Catch (MonadThrow, throwM)+import Control.Monad.IO.Class (MonadIO, liftIO) import Control.Monad.Trans.Class (lift) import qualified Data.Attoparsec.ByteString.Char8 as A import qualified Data.ByteString.Char8 as B import Data.Char (isSpace) import Data.List (isSuffixOf)-import Pipes (Producer, next)+import qualified Data.Streaming.Zlib as Z+import Pipes (Consumer, Producer, next, await) import Pipes.Attoparsec (ParsingError (..), parsed) import qualified Pipes.ByteString as PB import Pipes.GZip (decompress) import qualified Pipes.Safe as PS import qualified Pipes.Safe.Prelude as PS-import System.IO (IOMode (..))+import System.IO (Handle, IOMode (..)) -- |An exception type for parsing BioInformatic file formats. data SeqFormatException = SeqFormatException String@@ -75,12 +77,29 @@ consumeProducer parser prod = parsed parser prod >>= liftParsingErrors readFileProd :: (PS.MonadSafe m) => FilePath -> Producer B.ByteString m ()-readFileProd f = PS.withFile f ReadMode (\h -> PB.fromHandle h)+readFileProd f = PS.withFile f ReadMode PB.fromHandle readFileProdCheckCompress :: (PS.MonadSafe m) => FilePath -> Producer B.ByteString m () readFileProdCheckCompress f = let decompressFunc = if ".gz" `isSuffixOf` f then decompress else id- in decompressFunc $ PS.withFile f ReadMode (\h -> PB.fromHandle h)+ in decompressFunc $ PS.withFile f ReadMode PB.fromHandle word :: A.Parser B.ByteString word = A.takeTill isSpace++gzipConsumer :: (MonadIO m) => Z.Deflate -> Handle -> Consumer B.ByteString m ()+gzipConsumer def h = do+ bs <- await+ pop <- liftIO (Z.feedDeflate def bs)+ liftIO (writeFromPopper pop h)+ gzipConsumer def h++writeFromPopper :: (MonadIO m) => Z.Popper -> Handle -> m ()+writeFromPopper pop h = do+ popResult <- liftIO pop+ case popResult of+ Z.PRDone -> return ()+ Z.PRError e -> liftIO $ throwIO e+ Z.PRNext bs -> do+ liftIO $ B.hPut h bs+ writeFromPopper pop h
test/SequenceFormats/EigenstratSpec.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-}-module SequenceFormats.EigenstratSpec (spec) where+module SequenceFormats.EigenstratSpec where import Control.Foldl (list, purely) import Control.Monad.IO.Class (liftIO) import Data.Vector (fromList)-import Pipes (each, runEffect, (>->))+import Pipes (each) import qualified Pipes.Prelude as P import Pipes.Safe (runSafeT) import SequenceFormats.Eigenstrat (EigenstratIndEntry (..),@@ -19,6 +19,7 @@ testReadEigenstrat testReadEigenstratCompressed testWriteEigenstrat+ testWriteEigenstratCompressed mockDatEigenstratSnp :: [EigenstratSnpEntry] mockDatEigenstratSnp = [@@ -82,8 +83,23 @@ testDatSnpProd = each mockDatEigenstratSnp testDatGenoProd = each mockDatEigenstratGeno testDatJointProd = P.zip testDatSnpProd testDatGenoProd- liftIO . runSafeT . runEffect $- testDatJointProd >-> writeEigenstrat tmpGeno tmpSnp tmpInd mockDatEigenstratInd+ runSafeT $ writeEigenstrat tmpGeno tmpSnp tmpInd mockDatEigenstratInd testDatJointProd+ (indEntries, esProd) <- liftIO . runSafeT $ readEigenstrat tmpGeno tmpSnp tmpInd+ indEntries `shouldBe` mockDatEigenstratInd+ snpGenoEntries <- liftIO . runSafeT $ purely P.fold list esProd+ (map fst snpGenoEntries) `shouldBe` mockDatEigenstratSnp+ (map snd snpGenoEntries) `shouldBe` mockDatEigenstratGeno++testWriteEigenstratCompressed :: Spec+testWriteEigenstratCompressed = describe "writeEigenstrat with gzip" $ do+ it "should write and read back eigenstrat data correctly" $ do+ let tmpGeno = "/tmp/eigenstratWriteTestGzip.geno.gz"+ tmpSnp = "/tmp/eigenstratWriteTestGzip.snp.gz"+ tmpInd = "/tmp/eigenstratWriteTestGzip.ind"+ testDatSnpProd = each mockDatEigenstratSnp+ testDatGenoProd = each mockDatEigenstratGeno+ testDatJointProd = P.zip testDatSnpProd testDatGenoProd+ runSafeT $ writeEigenstrat tmpGeno tmpSnp tmpInd mockDatEigenstratInd testDatJointProd (indEntries, esProd) <- liftIO . runSafeT $ readEigenstrat tmpGeno tmpSnp tmpInd indEntries `shouldBe` mockDatEigenstratInd snpGenoEntries <- liftIO . runSafeT $ purely P.fold list esProd
test/SequenceFormats/PlinkSpec.hs view
@@ -16,7 +16,7 @@ import Control.Foldl (list, purely) import Control.Monad.IO.Class (liftIO) import Data.Vector (fromList)-import Pipes (each, runEffect, (>->))+import Pipes (each) import qualified Pipes.Prelude as P import Pipes.Safe (runSafeT) import Test.Hspec@@ -30,6 +30,7 @@ testReadBedFileCompressed testReadPlink testWritePlink+ testWritePlinkCompressed testFam2Ind testInd2Fam @@ -117,9 +118,24 @@ testDatSnpProd = each mockDatEigenstratSnp testDatGenoProd = each mockDatPlinkBed testDatJointProd = P.zip testDatSnpProd testDatGenoProd- liftIO . runSafeT . runEffect $- testDatJointProd >-> writePlink tmpGeno tmpSnp tmpInd mockDatPlinkFam+ runSafeT $ writePlink tmpGeno tmpSnp tmpInd mockDatPlinkFam testDatJointProd (indEntries, esProd) <- liftIO . runSafeT $ readPlink tmpGeno tmpSnp tmpInd+ indEntries `shouldBe` mockDatPlinkFam+ snpGenoEntries <- liftIO . runSafeT $ purely P.fold list esProd+ (map fst snpGenoEntries) `shouldBe` mockDatEigenstratSnp+ (map snd snpGenoEntries) `shouldBe` mockDatPlinkBed++testWritePlinkCompressed :: Spec+testWritePlinkCompressed = describe "writePlink with gzip" $ do+ it "should write and read back Plink data correctly" $ do+ let tmpBed = "/tmp/plinkWriteTestGzip.bed.gz"+ tmpBim = "/tmp/plinkWriteTestGzip.bim.gz"+ tmpFam = "/tmp/plinkWriteTestGzip.fam"+ testDatSnpProd = each mockDatEigenstratSnp+ testDatGenoProd = each mockDatPlinkBed+ testDatJointProd = P.zip testDatSnpProd testDatGenoProd+ runSafeT $ writePlink tmpBed tmpBim tmpFam mockDatPlinkFam testDatJointProd+ (indEntries, esProd) <- liftIO . runSafeT $ readPlink tmpBed tmpBim tmpFam indEntries `shouldBe` mockDatPlinkFam snpGenoEntries <- liftIO . runSafeT $ purely P.fold list esProd (map fst snpGenoEntries) `shouldBe` mockDatEigenstratSnp