Skip to content

Commit

Permalink
Allow empty input in TransferReadTags (#8198)
Browse files Browse the repository at this point in the history
  • Loading branch information
kachulis authored Feb 15, 2023
1 parent f7dea3c commit a88ac4e
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,11 @@ public void onTraversalStart(){
if (unmappedSamIterator.hasNext()){
currentUnmappedRead = unmappedSamIterator.next();
} else {
throw new UserException("unmapped sam iterator is empty.");
if (alignedSamIterator.hasNext()) {
throw new UserException("Unmapped sam iterator is empty and aligned sam iterator is not.");
} else {
logger.warn("Input data contains no reads. Output will also contain no reads.");
}
}

writer = createSAMWriter(new GATKPath(outSamFile.getAbsolutePath()), false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,86 +17,108 @@

import java.io.File;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class TransferReadTagsIntegrationTest extends CommandLineProgramTest {
@DataProvider(name = "testSAMPairs")
public Object[][] getTestSAMPairs(){
final File alignedSAMFile = createTempFile("sam1", ".bam");
final File alignedSAMWithExistingTagFile = createTempFile("sam2", ".bam");
final File unmappedSAMFile = createTempFile("sam3", ".bam");

final SAMFileHeader samHeader = M2TestingUtils.createSamHeader("sample");
samHeader.setSortOrder(SAMFileHeader.SortOrder.queryname);
// Often an unaligned bam does not have the SortOrder field populated.
final SAMFileHeader unalignedHeader = M2TestingUtils.createSamHeader("sample");

final List<String> umis = Arrays.asList("TCC-ATG", "CTA-GGA", "CCT-AGC", "GCA-AAA");
public File getSamFile(final String prefix, final boolean aligned, final SAMFileHeader.SortOrder sortOrder, final Map<String, String> readNamesAndUmis) {
final int readLength = 30;
final byte[] bases = new byte[readLength];
final byte[] quals = new byte[readLength];
Arrays.fill(bases, (byte)'A');
Arrays.fill(quals, (byte)30);

try (final SAMFileGATKReadWriter alignedSAMWriter = new SAMFileGATKReadWriter(ReadUtils.createCommonSAMWriter(alignedSAMFile, null, samHeader, true, false, false));
final SAMFileGATKReadWriter alignedSAMWithExisingTagWriter = new SAMFileGATKReadWriter(ReadUtils.createCommonSAMWriter(alignedSAMWithExistingTagFile, null, samHeader, true, false, false));
final SAMFileGATKReadWriter unmappedWriter = new SAMFileGATKReadWriter(ReadUtils.createCommonSAMWriter(unmappedSAMFile, null, unalignedHeader, true, false, false))) {
final File samFile = createTempFile(prefix, ".bam");
final SAMFileHeader samHeader = M2TestingUtils.createSamHeader("sample");
if (sortOrder != null) {
samHeader.setSortOrder(sortOrder);
}

for (int i = 0; i < umis.size(); i++) {
final GATKRead unmappedRead = ArtificialReadUtils.createArtificialUnmappedRead(samHeader, bases, quals);
unmappedRead.setName("read" + i);
unmappedRead.setAttribute("RX", umis.get(i));
unmappedWriter.addRead(unmappedRead);
try (final SAMFileGATKReadWriter samWriter = new SAMFileGATKReadWriter(ReadUtils.createCommonSAMWriter(samFile, null, samHeader, true, false, false))) {
for (final Map.Entry<String, String> readNameAndUMI : readNamesAndUmis.entrySet()) {
final GATKRead read = aligned? ArtificialReadUtils.createArtificialRead(samHeader, bases, quals, "30M") :
ArtificialReadUtils.createArtificialUnmappedRead(samHeader, bases, quals);
read.setName(readNameAndUMI.getKey());
final String umi = readNameAndUMI.getValue();
if (umi != null) {
read.setAttribute("RX", umi);
}
samWriter.addRead(read);
}
} catch (RuntimeIOException e){
throw new UserException("Failed to open SAM writers", e);
}

for (int i = 0; i < umis.size(); i++) {
final GATKRead alignedRead = ArtificialReadUtils.createArtificialRead(samHeader, bases, quals, "30M");
alignedRead.setName("read" + i);

// Simulate the case where an aligner drops a read
if (i == 1) {
continue;
}
return samFile;
}

alignedSAMWriter.addRead(alignedRead);

// When there the same tag exists in the aligned bam, it should be overwritten.
final GATKRead alignedReadWithExistingTag = alignedRead.copy();
alignedReadWithExistingTag.setAttribute("RX", "ZZZ-ZZZ");
alignedSAMWithExisingTagWriter.addRead(alignedReadWithExistingTag);
@DataProvider(name = "testSAMPairs")
public Object[][] getTestSAMPairs(){
final List<String> umis = Arrays.asList("TCC-ATG", "CTA-GGA", "CCT-AGC", "GCA-AAA");
final LinkedHashMap<String, String> alignedUMIsMap = new LinkedHashMap<>();
final LinkedHashMap<String, String> unmappedUMIsMap = new LinkedHashMap<>();
final LinkedHashMap<String, String> alignedWithExistingTagsUMIsMap = new LinkedHashMap<>();
final LinkedHashMap<String, String> expectedUMIsMap = new LinkedHashMap<>();

for (int i = 0; i < umis.size(); i++) {
if (i != 1) {
alignedUMIsMap.put("read" + i, null);
alignedWithExistingTagsUMIsMap.put("read"+ i, "ZZZ");
expectedUMIsMap.put("read"+ i, umis.get(i));
}
unmappedUMIsMap.put("read" + i, umis.get(i));

} catch (RuntimeIOException e){
throw new UserException("Failed to open SAM writers", e);
}
return new Object[][]{{alignedSAMFile, unmappedSAMFile, umis },
{alignedSAMWithExistingTagFile, unmappedSAMFile, umis }
final File alignedSAMFile = getSamFile("aligned", true, SAMFileHeader.SortOrder.queryname, alignedUMIsMap);
final File alignedSAMWithExistingTagFile = getSamFile("aligned_with_existing_tag", true, SAMFileHeader.SortOrder.queryname, alignedWithExistingTagsUMIsMap);
final File unmappedSAMFile = getSamFile("unmapped", false, null, unmappedUMIsMap);
final File emptySAMFile = getSamFile("empty", false, SAMFileHeader.SortOrder.queryname, Collections.emptyMap());

return new Object[][]{{alignedSAMFile, unmappedSAMFile, expectedUMIsMap },
{alignedSAMWithExistingTagFile, unmappedSAMFile, expectedUMIsMap},
{emptySAMFile, emptySAMFile, Collections.emptyMap()},
{emptySAMFile, unmappedSAMFile, Collections.emptyMap()}
};
}

@Test(dataProvider = "testSAMPairs")
public void test(final File alignedSAMFile, final File unmappedSAMFile, List<String> umis ) {
public void test(final File alignedSAMFile, final File unmappedSAMFile, final Map<String, String> expectedReadNamesAndUmis) {
final File outputFile = createTempFile("output", ".bam");
final ArgumentsBuilder args = new ArgumentsBuilder()
.add("I", alignedSAMFile.getAbsolutePath())
.add("unmapped-sam", unmappedSAMFile.getAbsolutePath())
.add("read-tags", "RX")
.add("O", outputFile.getAbsolutePath());
runCommandLine(args, TransferReadTags.class.getSimpleName());
runCommandLine(args);

final ReadsPathDataSource outputReadSource = new ReadsPathDataSource(outputFile.toPath());
final Iterator<GATKRead> outputSamIterator = outputReadSource.iterator();

for (int i = 0; i < umis.size(); i++){
// Skip the same read we removed above
if (i == 1){
continue;
}

final GATKRead outputRead = outputSamIterator.next();
Assert.assertEquals(outputRead.getName(), "read" + i);
Assert.assertEquals(outputRead.getAttributeAsString("RX"), umis.get(i));
final Set<String> observedReadName = new HashSet<>();
for (GATKRead outputRead : outputReadSource) {
Assert.assertTrue(expectedReadNamesAndUmis.containsKey(outputRead.getName()));
observedReadName.add(outputRead.getName());
Assert.assertEquals(outputRead.getAttributeAsString("RX"), expectedReadNamesAndUmis.get(outputRead.getName()));
}
Assert.assertTrue(observedReadName.containsAll(expectedReadNamesAndUmis.keySet()));
}

@Test(expectedExceptions = UserException.class, expectedExceptionsMessageRegExp = "Unmapped sam iterator is empty and aligned sam iterator is not.")
public void testEmptyUnmapped() {
final File alignedSAMFile = getSamFile("aligned", true, SAMFileHeader.SortOrder.queryname, Collections.singletonMap("read0", null));
final File emptySAMFile = getSamFile("empty", false, SAMFileHeader.SortOrder.queryname, Collections.emptyMap());
final File outputFile = createTempFile("output", ".bam");
final ArgumentsBuilder args = new ArgumentsBuilder()
.add("I", alignedSAMFile.getAbsolutePath())
.add("unmapped-sam", emptySAMFile.getAbsolutePath())
.add("read-tags", "RX")
.add("O", outputFile.getAbsolutePath());
runCommandLine(args);
}
}

0 comments on commit a88ac4e

Please sign in to comment.