diff --git a/src/main/java/picard/sam/SamToFastq.java b/src/main/java/picard/sam/SamToFastq.java index 668ff1ced..da217277a 100755 --- a/src/main/java/picard/sam/SamToFastq.java +++ b/src/main/java/picard/sam/SamToFastq.java @@ -84,20 +84,25 @@ public File INPUT; @Option(shortName = "F", doc = "Output FASTQ file (single-end fastq or, if paired, first end of the pair FASTQ).", - mutex = {"OUTPUT_PER_RG"}) + mutex = {"OUTPUT_PER_RG", "COMPRESS_OUTPUTS_PER_RG"}) public File FASTQ; @Option(shortName = "F2", doc = "Output FASTQ file (if paired, second end of the pair FASTQ).", optional = true, - mutex = {"OUTPUT_PER_RG"}) + mutex = {"OUTPUT_PER_RG", "COMPRESS_OUTPUTS_PER_RG"}) public File SECOND_END_FASTQ; - @Option(shortName = "FU", doc = "Output FASTQ file for unpaired reads; may only be provided in paired-FASTQ mode", optional = true, mutex = {"OUTPUT_PER_RG"}) + @Option(shortName = "FU", doc = "Output FASTQ file for unpaired reads; may only be provided in paired-FASTQ mode", optional = true, + mutex = {"OUTPUT_PER_RG", "COMPRESS_OUTPUTS_PER_RG"}) public File UNPAIRED_FASTQ; @Option(shortName = "OPRG", doc = "Output a FASTQ file per read group (two FASTQ files per read group if the group is paired).", optional = true, mutex = {"FASTQ", "SECOND_END_FASTQ", "UNPAIRED_FASTQ"}) public boolean OUTPUT_PER_RG; + @Option(shortName = "GZOPRG", doc = "Compress output FASTQ files per read group using gzip and append a .gz extension to the file names.", + optional = false, mutex = {"FASTQ", "SECOND_END_FASTQ", "UNPAIRED_FASTQ"}) + public Boolean COMPRESS_OUTPUTS_PER_RG = false; + @Option(shortName="RGT", doc = "The read group tag (PU or ID) to be used to output a FASTQ file per read group.") public String RG_TAG = "PU"; @@ -285,7 +290,7 @@ private File makeReadGroupFile(final SAMReadGroupRecord readGroup, final String } fileName = IOUtil.makeFileNameSafe(fileName); if (preExtSuffix != null) fileName += preExtSuffix; - fileName += ".fastq"; + fileName += COMPRESS_OUTPUTS_PER_RG ? ".fastq.gz" : ".fastq"; final File result = (OUTPUT_DIR != null) ? new File(OUTPUT_DIR, fileName) diff --git a/src/test/java/picard/sam/SamToFastqTest.java b/src/test/java/picard/sam/SamToFastqTest.java index c0464e961..834f6a665 100644 --- a/src/test/java/picard/sam/SamToFastqTest.java +++ b/src/test/java/picard/sam/SamToFastqTest.java @@ -38,6 +38,7 @@ import picard.PicardException; import java.io.File; +import java.io.FileInputStream; import java.io.IOException; import java.util.HashMap; import java.util.HashSet; @@ -451,10 +452,44 @@ else if (record.getSecondOfPairFlag()) { } } - private File newTempFastqFile(final String filename) throws IOException { + private File newTempFastqFile(final String filename, final String suffix) throws IOException { if(filename == null) return null; - final File file = File.createTempFile(filename,".fastq"); + final File file = File.createTempFile(filename, suffix); file.deleteOnExit(); return file; } + + private File newTempFastqFile(final String filename) throws IOException { + return newTempFastqFile(filename, ".fastq"); + } + + @Test(dataProvider = "okFiles") + public void testFileCompression(final String samFilename) throws IOException { + final File samFile = new File(TEST_DATA_DIR,samFilename); + final File pair1File = newTempFastqFile("pair1", ".fastq.gz"); + final File pair2File = newTempFastqFile("pair2", ".fastq.gz"); + + convertFile(new String[]{ + "INPUT=" + samFile.getAbsolutePath(), + "FASTQ=" + pair1File.getAbsolutePath(), + "SECOND_END_FASTQ=" + pair2File.getAbsolutePath() + }); + + verifyFileIsGzCompressed(pair1File); + verifyFileIsGzCompressed(pair2File); + // Content verification. Picard automatically recognizes the compression from the .gz suffix + // (htsjdk.samtools.util.IOUtil#openFileForReading(java.nio.file.Path)). + verifyFastq(pair1File, pair2File, samFile); + } + + private void verifyFileIsGzCompressed(final File file) throws IOException { + FileInputStream fis = new FileInputStream(file); + final byte[] expectedMagicNumber = { (byte) 0x1f, (byte) 0x8b}; + byte[] observedMagicNumber = new byte[2]; + fis.read(observedMagicNumber, 0, 2); + fis.close(); + Assert.assertEquals(observedMagicNumber, expectedMagicNumber); + } + + }