it = reader.iterator(); it.hasNext(); ) {
@@ -127,8 +128,9 @@ protected int doWork() {
libraryToWriter.get(rg.getLibrary()).addAlignment(sam);
} else {
if (unknown == null) {
- unknown = factory.makeSAMOrBAMWriter(unknownHeader, true,
- new File(OUTPUT, "unknown" + extension));
+ unknown = factory.makeWriter(unknownHeader, true,
+ new File(OUTPUT, "unknown" + extension),
+ REFERENCE_SEQUENCE);
}
unknown.addAlignment(sam);
}
diff --git a/src/main/java/picard/sam/markduplicates/MarkDuplicates.java b/src/main/java/picard/sam/markduplicates/MarkDuplicates.java
index 0141c4bdc..cf267c2e8 100644
--- a/src/main/java/picard/sam/markduplicates/MarkDuplicates.java
+++ b/src/main/java/picard/sam/markduplicates/MarkDuplicates.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright (c) 2009 The Broad Institute
+ * Copyright (c) 2009-2016 The Broad Institute
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -64,7 +64,7 @@
)
public class MarkDuplicates extends AbstractMarkDuplicatesCommandLineProgram {
static final String USAGE_SUMMARY = "Identifies duplicate reads. ";
- static final String USAGE_DETAILS = "This tool locates and tags duplicate reads in a BAM or SAM file, where duplicate reads are " +
+ static final String USAGE_DETAILS = "
This tool locates and tags duplicate reads in a SAM, BAM or CRAM file, where duplicate reads are " +
"defined as originating from a single fragment of DNA. Duplicates can arise during sample preparation e.g. library " +
"construction using PCR. See also " +
"EstimateLibraryComplexity" +
@@ -77,16 +77,16 @@
" collected, the tool differentiates the primary and duplicate reads using an algorithm that ranks reads by the sums " +
"of their base-quality scores (default method).
" +
- "The tool's main output is a new SAM or BAM file, in which duplicates have been identified in the SAM flags field for each" +
+ "
The tool's main output is a new SAM, BAM or CRAM file, in which duplicates have been identified in the SAM flags field for each" +
" read. Duplicates are marked with the hexadecimal value of 0x0400, which corresponds to a decimal value of 1024. " +
"If you are not familiar with this type of annotation, please see the following " +
"blog post for additional information.
" +
"" +
"Although the bitwise flag annotation indicates whether a read was marked as a duplicate, it does not identify the type of " +
"duplicate. To do this, a new tag called the duplicate type (DT) tag was recently added as an optional output in " +
- "the 'optional field' section of a SAM/BAM file. Invoking the TAGGING_POLICY option," +
+ "the 'optional field' section of a SAM/BAM/CRAM file. Invoking the TAGGING_POLICY option," +
" you can instruct the program to mark all the duplicates (All), only the optical duplicates (OpticalOnly), or no " +
- "duplicates (DontTag). The records within the output of a SAM/BAM file will have values for the 'DT' tag (depending on the invoked " +
+ "duplicates (DontTag). The records within the output of a SAM/BAM/CRAM file will have values for the 'DT' tag (depending on the invoked " +
"TAGGING_POLICY), as either library/PCR-generated duplicates (LB), or sequencing-platform artifact duplicates (SQ). " +
"This tool uses the READ_NAME_REGEX and the OPTICAL_DUPLICATE_PIXEL_DISTANCE options as the primary methods to identify " +
"and differentiate duplicate types. Set READ_NAME_REGEX to null to skip optical duplicate detection, e.g. for RNA-seq " +
@@ -119,7 +119,7 @@
/** Enum used to control how duplicates are flagged in the DT optional tag on each read. */
public enum DuplicateTaggingPolicy { DontTag, OpticalOnly, All }
- /** The optional attribute in SAM/BAM files used to store the duplicate type. */
+ /** The optional attribute in SAM/BAM/CRAM files used to store the duplicate type. */
public static final String DUPLICATE_TYPE_TAG = "DT";
/** The duplicate type tag value for duplicate type: library. */
public static final String DUPLICATE_TYPE_LIBRARY = "LB";
@@ -205,7 +205,7 @@ public static void main(final String[] args) {
}
/**
- * Main work method. Reads the BAM file once and collects sorted information about
+ * Main work method. Reads the SAM file once and collects sorted information about
* the 5' ends of both ends of each read (or just one end in the case of pairs).
* Then makes a pass through those determining duplicates before re-reading the
* input file and writing it out with duplication flags set correctly.
@@ -250,9 +250,10 @@ protected int doWork() {
// Key: previous PG ID on a SAM Record (or null). Value: New PG ID to replace it.
final Map chainedPgIds = getChainedPgIds(outputHeader);
- final SAMFileWriter out = new SAMFileWriterFactory().makeSAMOrBAMWriter(outputHeader,
+ final SAMFileWriter out = new SAMFileWriterFactory().makeWriter(outputHeader,
true,
- OUTPUT);
+ OUTPUT,
+ REFERENCE_SEQUENCE);
// Now copy over the file while marking all the necessary indexes as duplicates
long recordInFileIndex = 0;
diff --git a/src/main/java/picard/sam/markduplicates/MarkDuplicatesWithMateCigar.java b/src/main/java/picard/sam/markduplicates/MarkDuplicatesWithMateCigar.java
index fb9aff26a..564cb18a3 100644
--- a/src/main/java/picard/sam/markduplicates/MarkDuplicatesWithMateCigar.java
+++ b/src/main/java/picard/sam/markduplicates/MarkDuplicatesWithMateCigar.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright (c) 2014 The Broad Institute
+ * Copyright (c) 2014-2016 The Broad Institute
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -64,7 +64,7 @@
)
public class MarkDuplicatesWithMateCigar extends AbstractMarkDuplicatesCommandLineProgram {
static final String USAGE_SUMMARY = "Identifies duplicate reads, accounting for mate CIGAR. ";
- static final String USAGE_DETAILS = "This tool locates and tags duplicate reads (both PCR and optical) in a BAM or SAM file, where " +
+ static final String USAGE_DETAILS = "This tool locates and tags duplicate reads (both PCR and optical) in a BAM, SAM or CRAM file, where " +
"duplicate reads are defined as originating from the same original fragment of DNA, taking into account the CIGAR string of " +
"read mates.
" +
"" +
@@ -136,9 +136,10 @@ protected int doWork() {
final Map chainedPgIds = getChainedPgIds(outputHeader);
// Open the output
- final SAMFileWriter out = new SAMFileWriterFactory().makeSAMOrBAMWriter(outputHeader,
+ final SAMFileWriter out = new SAMFileWriterFactory().makeWriter(outputHeader,
true,
- OUTPUT);
+ OUTPUT,
+ REFERENCE_SEQUENCE);
// Create the mark duplicate iterator. The duplicate marking is handled by the iterator, conveniently.
final MarkDuplicatesWithMateCigarIterator iterator = new MarkDuplicatesWithMateCigarIterator(headerAndIterator.header,
diff --git a/src/main/java/picard/sam/markduplicates/SimpleMarkDuplicatesWithMateCigar.java b/src/main/java/picard/sam/markduplicates/SimpleMarkDuplicatesWithMateCigar.java
index e8fe4d064..baac38a30 100644
--- a/src/main/java/picard/sam/markduplicates/SimpleMarkDuplicatesWithMateCigar.java
+++ b/src/main/java/picard/sam/markduplicates/SimpleMarkDuplicatesWithMateCigar.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright (c) 2015 The Broad Institute
+ * Copyright (c) 2015-2016 The Broad Institute
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -62,9 +62,9 @@
* @author nhomer
*/
@CommandLineProgramProperties(
- usage = "Examines aligned records in the supplied SAM or BAM file to locate duplicate molecules. " +
+ usage = "Examines aligned records in the supplied SAM/BAM/CRAM file to locate duplicate molecules. " +
"All records are then written to the output file with the duplicate records flagged.",
- usageShort = "Examines aligned records in the supplied SAM or BAM file to locate duplicate molecules.",
+ usageShort = "Examines aligned records in the supplied SAM/BAM/CRAM file to locate duplicate molecules.",
programGroup = Testing.class
)
public class SimpleMarkDuplicatesWithMateCigar extends MarkDuplicates {
@@ -110,9 +110,10 @@ protected int doWork() {
final Map chainedPgIds = getChainedPgIds(outputHeader);
// Open the output
- final SAMFileWriter out = new SAMFileWriterFactory().makeSAMOrBAMWriter(outputHeader,
+ final SAMFileWriter out = new SAMFileWriterFactory().makeWriter(outputHeader,
false,
- OUTPUT);
+ OUTPUT,
+ REFERENCE_SEQUENCE);
final SAMRecordDuplicateComparator comparator = new SAMRecordDuplicateComparator(Collections.singletonList(headerAndIterator.header));
comparator.setScoringStrategy(this.DUPLICATE_SCORING_STRATEGY);
diff --git a/src/main/java/picard/sam/markduplicates/util/AbstractMarkDuplicatesCommandLineProgram.java b/src/main/java/picard/sam/markduplicates/util/AbstractMarkDuplicatesCommandLineProgram.java
index 5bf6972f4..d0bbd6caa 100644
--- a/src/main/java/picard/sam/markduplicates/util/AbstractMarkDuplicatesCommandLineProgram.java
+++ b/src/main/java/picard/sam/markduplicates/util/AbstractMarkDuplicatesCommandLineProgram.java
@@ -36,7 +36,6 @@
import htsjdk.samtools.metrics.MetricsFile;
import htsjdk.samtools.util.CloseableIterator;
import htsjdk.samtools.util.Histogram;
-import htsjdk.samtools.util.Log;
import picard.PicardException;
import picard.cmdline.Option;
import picard.cmdline.StandardOptionDefinitions;
@@ -209,6 +208,7 @@ protected SamHeaderAndIterator openInputs() {
for (final String input : INPUT) {
SamReader reader = SamReaderFactory.makeDefault()
.enable(SamReaderFactory.Option.EAGERLY_DECODE)
+ .referenceSequence(REFERENCE_SEQUENCE)
.open(SamInputResource.of(input));
final SAMFileHeader header = reader.getFileHeader();
diff --git a/src/test/java/picard/sam/CramCompatibilityTest.java b/src/test/java/picard/sam/CramCompatibilityTest.java
new file mode 100644
index 000000000..0454b8b2c
--- /dev/null
+++ b/src/test/java/picard/sam/CramCompatibilityTest.java
@@ -0,0 +1,318 @@
+package picard.sam;
+
+import htsjdk.samtools.cram.CRAMException;
+import htsjdk.samtools.util.IOUtil;
+import htsjdk.samtools.util.TestUtil;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import picard.cmdline.CommandLineProgram;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+
+public class CramCompatibilityTest {
+
+ public static final String CRAM_FILE = "testdata/picard/sam/test_cram_file.cram";
+ public static final String CRAM_FILE_2 = "testdata/picard/sam/test_cram_file_with_crai.cram";
+ public static final String CRAM_FILE_ONE_PAIR = "testdata/picard/sam/one_pair.cram";
+ public static final String CRAM_FILE_ONE_PAIR_MC = "testdata/picard/sam/MarkDuplicates/one_pair_mc.cram";
+
+ public static final String CRAM_FILE_QUERRY_SORTED_UNMAPPED = "testdata/picard/sam/unmapped_queryname_sorted.cram";
+
+ public static final String REFERENCE_FILE = "testdata/picard/sam/test_cram_file.ref.fa";
+ public static final String FASTQ_FILE = "testdata/picard/sam/fastq2bam/fastq-sanger/5k-v1-Rhodobacter_LW1.sam.fastq";
+
+ public static final String CRAM_UNMAPPED = "testdata/picard/sam/SamFileConverterTest/unmapped.cram";
+
+ public static final String CRAM_UNMAPPED_PART_1 = "testdata/picard/sam/unmapped_part_1.cram";
+ public static final String CRAM_UNMAPPED_PART_2 = "testdata/picard/sam/unmapped_part_2.cram";
+
+ public static final String CRAM_SPLIT_UNMAPPED = "testdata/picard/sam/split_test_unmapped.cram";
+
+ public static final String MBA_ALIGNED_CRAM = "testdata/picard/sam/MergeBamAlignment/cliptest.aligned.cram";
+ public static final String MBA_UNMAPPED_CRAM = "testdata/picard/sam/MergeBamAlignment/cliptest.unmapped.cram";
+ public static final String MBA_REFERENCE = "testdata/picard/sam/MergeBamAlignment/cliptest.fasta";
+
+ @DataProvider(name = "programms")
+ public Object[][] getProgramWithParams() {
+ return new Object[][] {
+ { "picard.sam.AddOrReplaceReadGroups",
+ "RGID=4 " +
+ "RGLB=lib1 " +
+ "RGPL=illumina " +
+ "RGPU=unit1 " +
+ "RGSM=20"
+ },
+ {"picard.sam.CleanSam", null},
+ {"picard.sam.FixMateInformation", null},
+ {"picard.sam.markduplicates.MarkDuplicates", "M=m"},
+ {"picard.sam.MergeSamFiles", null},
+ {"picard.sam.PositionBasedDownsampleSam", "FRACTION=0.5"},
+ {"picard.sam.ReorderSam",
+ "REFERENCE=" + REFERENCE_FILE + " " +
+ "ALLOW_CONTIG_LENGTH_DISCORDANCE=true " +
+ "ALLOW_INCOMPLETE_DICT_CONCORDANCE=true "
+ },
+ {"picard.sam.SortSam", "SORT_ORDER=coordinate"},
+ };
+ }
+
+ @Test(dataProvider = "programms")
+ public void writingMetricsShouldWriteCRAMWhenCRAMWithReferenceIsInput(String program, String exParameters)
+ throws ClassNotFoundException, IllegalAccessException, InstantiationException, IOException {
+ final File outputFile = createTempCram(program);
+
+ assertSuccessLaunchProgram(program, CRAM_FILE, outputFile.getAbsolutePath(), exParameters, REFERENCE_FILE);
+ assertCRAM(outputFile);
+ }
+
+ @Test(dataProvider = "programms", expectedExceptions = CRAMException.class)
+ public void metricsShouldFailWithCRAMWithoutReference(String program, String exParameters)
+ throws IllegalAccessException, InstantiationException, ClassNotFoundException, IOException {
+ final File outputFile = createTempCram(program);
+
+ assertSuccessLaunchProgramWithNoReference(program, CRAM_FILE, outputFile.getAbsolutePath(), exParameters);
+ }
+
+ @Test(dataProvider = "programms")
+ public void writingMetricsShouldWriteCRAMWhenUnmappedCRAMWithoutReferenceIsInput(String program, String exParameters)
+ throws IOException, IllegalAccessException, InstantiationException, ClassNotFoundException {
+ final File outputFile = createTempCram(program);
+
+ assertSuccessLaunchProgramWithNoReference(program, CRAM_UNMAPPED, outputFile.getAbsolutePath(), exParameters);
+ assertCRAM(outputFile);
+ }
+
+
+ // Header should be specify personally for each input
+ @Test
+ public void testReplaceSamHeader() throws IOException, IllegalAccessException, InstantiationException, ClassNotFoundException {
+ String program = "picard.sam.ReplaceSamHeader";
+ final File outputFile = createTempCram(program);
+
+ assertSuccessLaunchProgram(program, CRAM_FILE, outputFile.getAbsolutePath(), "HEADER=" + CRAM_FILE_2, REFERENCE_FILE);
+ assertCRAM(outputFile);
+
+ assertFailingLaunch(program, CRAM_FILE, outputFile.getAbsolutePath(), "HEADER=" + CRAM_FILE_2, null);
+
+ assertSuccessLaunchProgramWithNoReference(program, CRAM_UNMAPPED, outputFile.getAbsolutePath(), "HEADER=" + CRAM_UNMAPPED);
+ assertCRAM(outputFile);
+ }
+
+ // Only works with paired reads
+ @Test
+ public void testRevertOriginalBaseQualitiesAndAddMateCigar() throws IOException, IllegalAccessException, InstantiationException, ClassNotFoundException {
+ String program = "picard.sam.RevertOriginalBaseQualitiesAndAddMateCigar";
+ final File outputFile = createTempCram(program);
+
+ assertSuccessLaunchProgram(program, CRAM_FILE_ONE_PAIR, outputFile.getAbsolutePath(), null, REFERENCE_FILE);
+ assertCRAM(outputFile);
+
+ assertFailingLaunch(program, CRAM_FILE_ONE_PAIR, outputFile.getAbsolutePath(), null, null);
+
+ assertSuccessLaunchProgramWithNoReference(program, CRAM_UNMAPPED, outputFile.getAbsolutePath(), null);
+ assertCRAM(outputFile);
+ }
+
+ // Several special inputs
+ @Test
+ public void testGatherBamFiles() throws IOException, IllegalAccessException, InstantiationException, ClassNotFoundException {
+ String program = "picard.sam.GatherBamFiles";
+ final File outputFile = createTempFile(program, ".cram");
+ final String input2 = new File(CRAM_UNMAPPED).getAbsolutePath();
+
+ assertSuccessLaunchProgram(program, CRAM_FILE_ONE_PAIR, outputFile.getAbsolutePath(), "I=" + input2, REFERENCE_FILE);
+ assertCRAM(outputFile);
+
+ assertFailingLaunch(program, CRAM_FILE_ONE_PAIR, outputFile.getAbsolutePath(), "I=" + input2, null);
+
+ assertSuccessLaunchProgramWithNoReference(program, CRAM_UNMAPPED_PART_1, outputFile.getAbsolutePath(), "I=" + new File(CRAM_UNMAPPED_PART_2).getAbsolutePath());
+ assertCRAM(outputFile);
+ }
+
+ // Needs directory as OUTPUT
+ @Test
+ public void testSplitSamByLibrary() throws IOException, IllegalAccessException, InstantiationException, ClassNotFoundException {
+ String program = "picard.sam.SplitSamByLibrary";
+ final File outputDir = IOUtil.createTempDir("SplitSamByLibrary", "");
+
+ try {
+ assertSuccessLaunchProgram(program, CRAM_FILE, outputDir.getPath(), null, REFERENCE_FILE);
+ assertCRAMs(outputDir);
+
+ assertFailingLaunch(program, CRAM_FILE, outputDir.getPath(), null, null);
+
+ assertSuccessLaunchProgramWithNoReference(program, CRAM_SPLIT_UNMAPPED, outputDir.getPath(), null);
+ assertCRAMs(outputDir);
+
+ } finally {
+ TestUtil.recursiveDelete(outputDir);
+ }
+ }
+
+ // Only Coordinate sorted - unmapped is not in use
+ @Test
+ public void testMarkDuplicatesWithMateCigar() throws IOException, IllegalAccessException, InstantiationException, ClassNotFoundException {
+ String program = "picard.sam.markduplicates.MarkDuplicatesWithMateCigar";
+ final File outputFile = createTempCram(program);
+ final File metricsFile = createTempFile(program, ".txt");
+
+ assertSuccessLaunchProgram(
+ program,
+ CRAM_FILE,
+ outputFile.getAbsolutePath(),
+ "M=" + metricsFile.getAbsolutePath(),
+ REFERENCE_FILE);
+ assertCRAM(outputFile);
+
+ assertFailingLaunch(program, CRAM_FILE, outputFile.getAbsolutePath(), "M=" + metricsFile.getAbsolutePath(), null);
+ }
+
+
+ @Test
+ public void testSimpleMarkDuplicatesWithMateCigar() throws IOException, IllegalAccessException, InstantiationException, ClassNotFoundException {
+ String program = "picard.sam.markduplicates.SimpleMarkDuplicatesWithMateCigar";
+ final File outputFile = createTempCram(program);
+ final File metricsFile = createTempFile(program, ".txt");
+
+ assertSuccessLaunchProgram(
+ program,
+ CRAM_FILE_ONE_PAIR_MC,
+ outputFile.getAbsolutePath(),
+ "M=" + metricsFile.getAbsolutePath(),
+ REFERENCE_FILE);
+ assertCRAM(outputFile);
+
+ assertFailingLaunch(program, CRAM_FILE_ONE_PAIR_MC, outputFile.getAbsolutePath(), "M=" + metricsFile.getAbsolutePath(), null);
+ }
+
+ @DataProvider(name = "programsWithArgs")
+ public static Object[][] programs() {
+ return new Object[][] {
+ {
+ "picard.sam.SetNmMdAndUqTags",
+ new String[] {
+ "I=" + CRAM_FILE,
+ "R=" + REFERENCE_FILE
+ },
+ },
+ {
+ "picard.illumina.MarkIlluminaAdapters",
+ new String[] {
+ "I=" + CRAM_FILE_QUERRY_SORTED_UNMAPPED,
+ "METRICS=" + createTempFile("picard.illumina.MarkIlluminaAdapters", ".txt").getAbsolutePath()
+ }
+ },
+ {
+ "picard.sam.FastqToSam",
+ new String[] {
+ "F1=" + FASTQ_FILE,
+ "SAMPLE_NAME=s1"
+ }
+ },
+ {
+ "picard.illumina.IlluminaBasecallsToSam",
+ new String[] {
+ "BASECALLS_DIR=" + new File("testdata/picard/illumina/25T8B25T/Data/Intensities/BaseCalls"),
+ "LANE=1",
+ "READ_STRUCTURE=25S8S25T",
+ "RUN_BARCODE=HiMom",
+ "SAMPLE_ALIAS=HiDad",
+ "LIBRARY_NAME=Hello, World"
+ }
+ },
+ {
+ "picard.sam.MergeBamAlignment",
+ new String[] {
+ "UNMAPPED=" + new File(MBA_UNMAPPED_CRAM).getAbsolutePath(),
+ "ALIGNED=" + new File(MBA_ALIGNED_CRAM).getAbsolutePath(),
+ "R=" + new File(MBA_REFERENCE).getAbsolutePath(),
+ }
+ }
+ };
+ }
+
+ @Test(dataProvider = "programsWithArgs")
+ public void programsShouldPassReferenceToReadCramFilesAndProduceCramFiles(String program, String[] args)
+ throws IOException, IllegalAccessException, InstantiationException, ClassNotFoundException {
+ final File outputCram = createTempCram(program);
+
+ final String[] argsWithOutput = Arrays.copyOf(args, args.length + 1);
+ argsWithOutput[argsWithOutput.length - 1] = "O=" + outputCram.getAbsolutePath();
+ assertSuccessLaunchCMDProgram(program, argsWithOutput);
+ assertCRAM(outputCram);
+ }
+
+ private File createTempCram(String name) throws IOException {
+ return createTempFile(name, ".cram");
+ }
+
+ private static File createTempFile(String name, String extension) {
+ File file = null;
+ try {
+ file = File.createTempFile(name, extension);
+ file.deleteOnExit();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ return file;
+ }
+
+ private void assertFailingLaunch(String program, String input, String outputFile, String exParameters, String reference) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
+ boolean exceptionCaught = false;
+ try {
+ assertSuccessLaunchProgram(program, input, outputFile, exParameters, reference);
+ } catch (CRAMException e) {
+ exceptionCaught = true;
+ }
+ Assert.assertTrue(exceptionCaught, "Metrics should fail with CRAM without reference");
+ }
+
+ private void assertSuccessLaunchProgramWithNoReference(String programClassname, String input, String output, String exParams) throws IllegalAccessException, InstantiationException, ClassNotFoundException {
+ assertSuccessLaunchProgram(programClassname, input, output, exParams, null);
+ }
+
+ private void assertSuccessLaunchProgram(String programClassname, String input, String output, String exParams, String reference) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
+ final Collection args = new ArrayList<>();
+
+ if (input != null) {
+ args.add("INPUT=" + new File(input).getAbsolutePath());
+ }
+ args.add("OUTPUT=" + output);
+
+ if (exParams != null) {
+ args.addAll(Arrays.asList(exParams.split(" ")));
+ }
+
+ if (reference != null) {
+ args.add("REFERENCE_SEQUENCE=" + new File(reference).getAbsolutePath());
+ }
+
+ assertSuccessLaunchCMDProgram(programClassname, args.toArray(new String[args.size()]));
+ }
+
+ private void assertSuccessLaunchCMDProgram(String programClassname, String... params) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
+ CommandLineProgram prog = (CommandLineProgram) Class.forName(programClassname).newInstance();
+
+ Assert.assertEquals(prog.instanceMain(params), 0);
+ }
+
+ static void assertCRAM(File outputFile) {
+ try (InputStream in = new FileInputStream(outputFile)) {
+ Assert.assertEquals(0x43, in.read(), "File is not CRAM");
+ Assert.assertEquals(0x52, in.read(), "File is not CRAM");
+ Assert.assertEquals(0x41, in.read(), "File is not CRAM");
+ Assert.assertEquals(0x4d, in.read(), "File is not CRAM");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ static private void assertCRAMs(File dir) {
+ Arrays.stream(dir.listFiles()).filter(file -> file.getName().endsWith("cram")).forEach(CramCompatibilityTest::assertCRAM);
+ }
+}
diff --git a/src/test/java/picard/sam/FilterSamReadsTest.java b/src/test/java/picard/sam/FilterSamReadsTest.java
index 71469c5ad..aa99dc029 100644
--- a/src/test/java/picard/sam/FilterSamReadsTest.java
+++ b/src/test/java/picard/sam/FilterSamReadsTest.java
@@ -69,22 +69,38 @@ public void setUp() {
{"testdata/picard/sam/FilterSamReads/filter2.interval_list", 0}
};
}
-
+
/**
* filters a SAM using a javascript filter
*/
@Test(dataProvider = "dataTestJsFilter")
public void testJavaScriptFilters(final String samFilename, final String javascriptFilename,final int expectNumber) throws Exception {
- // input as SAM file
+ launchJavaScriptFilter(samFilename, javascriptFilename, expectNumber);
+ }
+
+ @Test
+ public void testJavaScriptFiltersWithCRAM() throws Exception {
+ final FilterSamReads program = setupProgram(
+ new File("testdata/picard/sam/FilterSamReads/filterOddStarts.js"),
+ new File(CramCompatibilityTest.CRAM_FILE),
+ FilterSamReads.Filter.includeJavascript,
+ CramCompatibilityTest.REFERENCE_FILE);
+ Assert.assertEquals(program.doWork(), 0);
+ CramCompatibilityTest.assertCRAM(program.OUTPUT);
+ }
+
+ private FilterSamReads launchJavaScriptFilter(String samFilename, String javascriptFilename, int expectNumber) throws Exception {
+ // input as SAM file
final File inputSam = new File(samFilename);
final File javascriptFile = new File(javascriptFilename);
- FilterSamReads filterTest = setupProgram(javascriptFile, inputSam, FilterSamReads.Filter.includeJavascript);
- Assert.assertEquals(filterTest.doWork(),0);
-
+ FilterSamReads filterTest = setupProgram(javascriptFile, inputSam, FilterSamReads.Filter.includeJavascript, null);
+ Assert.assertEquals(filterTest.doWork(), 0);
long count = getReadCount(filterTest);
Assert.assertEquals(count, expectNumber);
+
+ return filterTest;
}
/**
@@ -106,7 +122,7 @@ public void testPairedIntervalFilter(final String intervalFilename, final int ex
final File intervalFile = new File(intervalFilename);
- FilterSamReads filterTest = setupProgram(intervalFile, inputSam, FilterSamReads.Filter.includePairedIntervals);
+ FilterSamReads filterTest = setupProgram(intervalFile, inputSam, FilterSamReads.Filter.includePairedIntervals, null);
Assert.assertEquals(filterTest.doWork(),0);
long count = getReadCount(filterTest);
@@ -114,20 +130,23 @@ public void testPairedIntervalFilter(final String intervalFilename, final int ex
Assert.assertEquals(count, expectNumber);
}
- private FilterSamReads setupProgram(final File inputFile, final File inputSam, final FilterSamReads.Filter filter) throws Exception {
+ private FilterSamReads setupProgram(final File inputFile, final File inputSam, final FilterSamReads.Filter filter, final String reference) throws Exception {
final FilterSamReads program = new FilterSamReads();
program.INPUT = inputSam;
- program.OUTPUT = File.createTempFile("FilterSamReads.output.", ".sam");
+ program.OUTPUT = File.createTempFile("FilterSamReads.output.", getFilenameExtension(inputSam.getAbsolutePath()));
program.OUTPUT.deleteOnExit();
program.FILTER = filter;
- if(filter == FilterSamReads.Filter.includePairedIntervals) {
+ if (filter == FilterSamReads.Filter.includePairedIntervals) {
program.INTERVAL_LIST = inputFile;
- }
- else {
+ } else {
program.JAVASCRIPT_FILE = inputFile;
}
+ if (reference != null) {
+ program.REFERENCE_SEQUENCE = new File(reference);
+ }
+
return program;
}
@@ -140,4 +159,9 @@ private long getReadCount(FilterSamReads filterTest) throws Exception {
samReader.close();
return count;
}
+
+ private static String getFilenameExtension(String samFilename) {
+ final String[] split = samFilename.split("\\.");
+ return "." + split[split.length - 1];
+ }
}
diff --git a/testdata/picard/sam/MarkDuplicates/one_pair_mc.cram b/testdata/picard/sam/MarkDuplicates/one_pair_mc.cram
new file mode 100644
index 0000000000000000000000000000000000000000..b4772a40aaee96171efe7431f1ce7bfff7e8cef8
GIT binary patch
literal 12495
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
M5JV(`eizFA4S|Y*=>Px#
literal 0
HcmV?d00001
diff --git a/testdata/picard/sam/one_pair.cram b/testdata/picard/sam/one_pair.cram
new file mode 100644
index 0000000000000000000000000000000000000000..1264ad2067a76f56b3ce9cadec9bd3aa6d54794c
GIT binary patch
literal 12434
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
literal 0
HcmV?d00001
diff --git a/testdata/picard/sam/split_test_unmapped.cram b/testdata/picard/sam/split_test_unmapped.cram
new file mode 100644
index 0000000000000000000000000000000000000000..58b8079670586ccaf0602afac05093a540402454
GIT binary patch
literal 2696
zcmeHI?N6Ik6u;-`?aT9&(iYmSP#UVDf^m$Np<5${J}oWHXkl&LA|g@>OavTbWoDQx
z53e=bvf+~b1@i^@f?qV_1L2DrV&d+s^ysW0jctBBvz?C&_*+|iflJ=m3M?(0e>`t_6$l3@ci0kTpNdJGq%_!&T5
zQ|IURM?9|bDn8cWIXuwOf9&-{Z--D54e}ws$Hm9Op3Xyu_$U7o5v#{Q>I_BY%AG$k#n9mx5n@_1w#2zkQe)v0X_Y|8-|_#x)!C4i3G$+dcT#
zlZ(&C{-bk5znEnG|EcE0{elU6+4w
z4heeG86QIA#qrXouYP{FOxE3l-GlR|=1-ZLOilIHNi9&V@^yiWsoOwx%HXB#DTz|P
zL;yS9kxj6Gj}n;3=2p%zbxLIH&)jiJg=ztI$z+nw05^>P@xw^xn8gwU=?urTik%{0
zN!J{NuI(YZ*Pc+Dp1HOZ2dY<&=lAlrG1#0(E%!=!WI45*;>3f_6o?0$l+4#Ow6JeO
zPIPr1sA0QskD6?ifE<1G#1ebR8`YP$QJPyUz_!h3m0nd|eB>-pqjEg0XTHFAOv>Op
zSLTL*nw7!6-4_di<|%_=DC+^5|3K_*!$4-bPq(nxSNhJ4P--c0XUpP756NKc874?c
ztF$>?eG+-)=6Q}%>-{xkiC1N_FV~N0R>QSU?=L`Y58Qlz)&l!2hbb)}WT55QX`qG5
z@pp?87{6T^oSR&_1GGpPG*>iX&K%0%r;BBUtT(V;Y5cLaf&D1)??FBLeFG|u22cW7
IO~T%P08jX!od5s;
literal 0
HcmV?d00001
diff --git a/testdata/picard/sam/test_cram_file.cram b/testdata/picard/sam/test_cram_file.cram
new file mode 100644
index 0000000000000000000000000000000000000000..fcdd9f9da3528487bf6038a514478afb8d34e3f2
GIT binary patch
literal 53606
zcmeFYb!=Qq^DSy-W@culm?>svW@ct)J7$L1am>ujj+vP$W@bC)J2@xk`+d4k?@9Om
z_oOo#sjI42t?FLgJ$q}S?=f-oBD
z?>^9TUtMS1&xz+7LtWh!8|EL9_2-?7zRK
znM}K&c-!*#zt_FK$(r?dsefWA+KN)gEc`f%B4m_u94&q@0Wb4#)O(JzW6>YHTig2~
z`#O|$KQvOWI%=7cN<2}gz11S0yN@xZ>2{i>-#q1gf08s+;@zT6M@iW&7eGnrd1G^a
zP|vGhFvV|jL)U&kQ4MfjfnQg3-;Tfgg)2NdTD#vf$jYsQMGWkjuzNPOWz!#wH9Y+)
zZ|C=mK8wCj%Qbp3dfU(4&KCYG7_`t2)K?Wy;D;qRj~(xWC0IvFG>iBH$sGa=5mdqz
zykNW^XjT`P4^5BrqAc7bv2bm8^Y}&Qjk1Mv#ZV_=vacSduhwG$ER{-sE
z&f{tLD#5qgur~udc)OvnN$rPV)5@2xZ-Scr7v2w`rts~TD~JP%k9;rRxK29E1?D+%
z|BB3PKiHggng2y$Gk_RUa{CoP;ksE*7)6S+{#7=3t=`hXn*-i%s;KvTW!`hjujcYM
zOJHp5f1oe#X4M-DX9r%Xhuwu-w+l1ZtGXLH`izU(4%Y6fy+O*;NsMZ0%8^?BnjKu-
zZ|zBlw|9U1^Tj0;wl<5)rZh+^XdK@L_qBF707P!J
z{d^&cC&@Y6#$iz9_+j=O98}^
z-p!pNs(`^1bgtKF%G;+WcewS*``cq1E
z_D?CZ-;?@XYNjbQkMg*Habtq99=EwohO_?ZhN6Bhholrp6IzEpTbM
zg3X)^&YX}&EV9Ke;t4f0IW{~%Ki)yhYoF5*R*!`
z8DFU{uj}tH|Dv_IsJ_B_Mdx@__keqc$$FvXh42rZcta-$?(REyhl%^&)8^OpX8>td
z7u83AH1&H{;9dcUkUf!T5|6^~DY;tLmady1D
ze8mTQ&i;1a6gKg)>#5--#F4Cxe#YIaVxw?S!bLm(lFhySaXI0rNp$OvNrNyw}G_
zbj#BGw^{ECFpt0gHVgfJN4I~QY5o9HllzRUEso@8B(m>e!j)Y93m5)xgl~qE`@rl_
z@164ZHe*LFwea)O3pIiVr<}V|#f?hAvwezFK#z9h@)-GQvAAn9Np0FoyZo0EJ5wV@
z_3&Jrg$j^0yx)T`yL@E}F(P=$ne$v>TVl;O~Dk
zSk3pH`HulX{Kqh3`eO_V{4prxzhW)8BetD&ed17y
z{ykv&2NwI=`I5hklYb1;yFZcbe+=#WKas_M48?~(k#RQ@mGINYu`JD&_iZ(2_oR#L
zMC[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]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