packages feed

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 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