Skip to content

Commit

Permalink
Cloud-enable BuildBamIndex outputs.
Browse files Browse the repository at this point in the history
  • Loading branch information
cmnbroad committed Dec 4, 2023
1 parent 98c86c4 commit 2b2d22c
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 33 deletions.
15 changes: 6 additions & 9 deletions src/main/java/picard/sam/BuildBamIndex.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -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);
Expand Down
65 changes: 41 additions & 24 deletions src/test/java/picard/sam/BuildBamIndexTest.java
Original file line number Diff line number Diff line change
@@ -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<String> 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<String> 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<String> 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<String> 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<String> 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);
}
}

0 comments on commit 2b2d22c

Please sign in to comment.