diff --git a/src/main/java/picard/sam/BuildBamIndex.java b/src/main/java/picard/sam/BuildBamIndex.java index 5141688328..89f6ed4100 100755 --- a/src/main/java/picard/sam/BuildBamIndex.java +++ b/src/main/java/picard/sam/BuildBamIndex.java @@ -75,7 +75,7 @@ public class BuildBamIndex extends CommandLineProgram { @Argument(shortName = StandardOptionDefinitions.OUTPUT_SHORT_NAME, doc = "The BAM index file. Defaults to x.bai if INPUT is x.bam, otherwise INPUT.bai.\n" + "If INPUT is a URL and OUTPUT is unspecified, defaults to a file in the current directory.", optional = true) - public File OUTPUT; + public PicardHtsPath OUTPUT; /** * Main method for the program. Checks that all input files are present and @@ -91,20 +91,17 @@ protected int doWork() { final String baseFileName = inputPath.getFileName().toString(); // only BAI indices can be created for now, although CSI indices can be read as well - if (baseFileName.endsWith(FileExtensions.BAM)) { + if (INPUT.hasExtension(FileExtensions.BAM)) { final int index = baseFileName.lastIndexOf('.'); - OUTPUT = new File(baseFileName.substring(0, index) + FileExtensions.BAI_INDEX); - + final String outputIndexFileName = baseFileName.substring(0, index) + FileExtensions.BAI_INDEX; + OUTPUT = new PicardHtsPath(inputPath.resolveSibling(outputIndexFileName).toUri().toString()); } else { - OUTPUT = new File(baseFileName + FileExtensions.BAI_INDEX); + OUTPUT = new PicardHtsPath(inputPath.resolveSibling(baseFileName + FileExtensions.BAI_INDEX).toUri().toString()); } } - IOUtil.assertFileIsWritable(OUTPUT); final SamReader bam; - - bam = SamReaderFactory.makeDefault().referenceSequence(REFERENCE_SEQUENCE) .disable(SamReaderFactory.Option.EAGERLY_DECODE) .enable(SamReaderFactory.Option.INCLUDE_SOURCE_IN_RECORDS) @@ -118,7 +115,7 @@ protected int doWork() { throw new SAMException("Input bam file must be sorted by coordinate"); } - BAMIndexer.createIndex(bam, OUTPUT); + BAMIndexer.createIndex(bam, OUTPUT.toPath()); log.info("Successfully wrote bam index file " + OUTPUT); CloserUtil.close(bam); diff --git a/src/test/java/picard/sam/BuildBamIndexTest.java b/src/test/java/picard/sam/BuildBamIndexTest.java index 1c01f7567d..a9f1cc8504 100644 --- a/src/test/java/picard/sam/BuildBamIndexTest.java +++ b/src/test/java/picard/sam/BuildBamIndexTest.java @@ -1,72 +1,89 @@ package picard.sam; +import htsjdk.beta.io.IOPathUtils; +import htsjdk.io.IOPath; import htsjdk.samtools.SAMException; import org.apache.commons.io.FileUtils; import org.testng.Assert; -import org.testng.annotations.AfterTest; import org.testng.annotations.Test; import picard.cmdline.CommandLineProgramTest; import picard.nio.PicardHtsPath; import java.io.File; import java.io.IOException; +import java.nio.file.Path; import java.util.ArrayList; import java.util.List; public class BuildBamIndexTest extends CommandLineProgramTest { private static final File TEST_DATA_DIR = new File("testdata/picard/indices/"); - private static final PicardHtsPath INPUT_FILE = new PicardHtsPath(new File(TEST_DATA_DIR, "index_test.sam").getPath()); - private static final File OUTPUT_SORTED_FILE = new File(TEST_DATA_DIR, "index_test_sorted.bam"); - private static final File OUTPUT_UNSORTED_FILE = new File(TEST_DATA_DIR, "/index_test_unsorted.bam"); - private static final File OUTPUT_INDEX_FILE = new File(TEST_DATA_DIR, "/index_test.bam.bai"); + private static final PicardHtsPath INPUT_UNSORTED_SAM = new PicardHtsPath(new File(TEST_DATA_DIR, "index_test.sam").getPath()); private static final File EXPECTED_BAI_FILE = new File(TEST_DATA_DIR, "index_test_b.bam.bai"); public String getCommandLineProgramName() { return BuildBamIndex.class.getSimpleName(); } - // Test that the index file for a sorted BAM is created @Test public void testBuildBamIndexOK() throws IOException { + final IOPath sortedBAM = IOPathUtils.createTempPath("index_test_sorted", ".bam"); + // don't create the output index file, but mark it for deletion + final Path indexOutput = sortedBAM.toPath().resolveSibling("index_test.bam.bai"); + indexOutput.toFile().deleteOnExit(); + + /* First sort, before indexing */ + new SortSam().instanceMain(new String[]{ + "I=" + INPUT_UNSORTED_SAM, + "O=" + sortedBAM, + "SORT_ORDER=coordinate"}); + final List args = new ArrayList<>(); + args.add("INPUT=" + sortedBAM); + args.add("OUTPUT=" + indexOutput); + runPicardCommandLine(args); + Assert.assertEquals(FileUtils.readFileToByteArray(indexOutput.toFile()), FileUtils.readFileToByteArray(EXPECTED_BAI_FILE)); + } + + // Test that the index file for a sorted BAM is created in the right place if no output file is specified + @Test + public void testBuildBamIndexDefaultOutput() throws IOException { + final IOPath sortedBAM = IOPathUtils.createTempPath("index_test_sorted", ".bam"); /* First sort, before indexing */ new SortSam().instanceMain(new String[]{ - "I=" + INPUT_FILE, - "O=" + OUTPUT_SORTED_FILE, + "I=" + INPUT_UNSORTED_SAM, + "O=" + sortedBAM, "SORT_ORDER=coordinate"}); - args.add("INPUT=" + OUTPUT_SORTED_FILE); - args.add("OUTPUT=" + OUTPUT_INDEX_FILE); + // don't create the output index file, but construct the expected name, and mark it for deletion + final String expectedIndexFileName = sortedBAM.getURIString().replace(".bam", ".bai"); + final IOPath indexOutput = new PicardHtsPath(expectedIndexFileName); + indexOutput.toPath().toFile().deleteOnExit(); + + final List args = new ArrayList<>(); + args.add("INPUT=" + sortedBAM); runPicardCommandLine(args); - Assert.assertEquals(FileUtils.readFileToByteArray(OUTPUT_INDEX_FILE), FileUtils.readFileToByteArray(EXPECTED_BAI_FILE)); + Assert.assertEquals(FileUtils.readFileToByteArray(indexOutput.toPath().toFile()), FileUtils.readFileToByteArray(EXPECTED_BAI_FILE)); } // Test that the index creation fails when presented with a SAM file @Test(expectedExceptions = SAMException.class) public void testBuildSamIndexFail() { final List args = new ArrayList<>(); - args.add("INPUT=" + INPUT_FILE); - args.add("OUTPUT=" + OUTPUT_INDEX_FILE); + args.add("INPUT=" + INPUT_UNSORTED_SAM); runPicardCommandLine(args); } // Test that the index creation fails when presented with an unsorted BAM file @Test(expectedExceptions = SAMException.class) public void testBuildBamIndexFail() { - final List args = new ArrayList<>(); + final IOPath unsortedBAM = IOPathUtils.createTempPath("index_test_sorted", ".bam"); new SamFormatConverter().instanceMain(new String[]{ - "INPUT=" + INPUT_FILE, - "OUTPUT=" + OUTPUT_UNSORTED_FILE}); + "INPUT=" + INPUT_UNSORTED_SAM, + "OUTPUT=" + unsortedBAM}); - args.add("INPUT=" + OUTPUT_UNSORTED_FILE); - args.add("OUTPUT=" + OUTPUT_INDEX_FILE); + final List args = new ArrayList<>(); + args.add("INPUT=" + unsortedBAM); runPicardCommandLine(args); } - @AfterTest - public void cleanup() throws IOException { - FileUtils.forceDeleteOnExit(OUTPUT_INDEX_FILE); - FileUtils.forceDeleteOnExit(OUTPUT_SORTED_FILE); - FileUtils.forceDeleteOnExit(OUTPUT_UNSORTED_FILE); - } }