/*
* The MIT License
*
* Copyright (c) 2009 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
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package htsjdk.samtools;
import htsjdk.samtools.util.SequenceUtil;
import org.testng.Assert;
import org.testng.annotations.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Tests for MultiIterator
*
* @author Dave Tefft
*/
public class MergingSamRecordIteratorTest {
@Test
public void testVanillaCoordinateMultiIterator() throws Exception {
final SAMRecordSetBuilder builder1 = new SAMRecordSetBuilder();
builder1.addFrag("read_28833_29006_6945", 20, 28833, false); // ok
builder1.addFrag("read_28701_28881_323b", 22, 28834, false); // ok
final SAMFileReader samReader = builder1.getSamReader();
samReader.getFileHeader().setSortOrder(SAMFileHeader.SortOrder.coordinate);
final SAMRecordSetBuilder builder2 = new SAMRecordSetBuilder();
builder2.addFrag("read_28833_29006_6945", 20, 30000, false); // ok
builder2.addFrag("read_28701_28881_323b", 22, 28835, false); // ok
builder2.addFrag("read_28701_28881_323c", 22, 28835, false); // ok
final SAMFileReader samReader2 = builder2.getSamReader();
samReader2.getFileHeader().setSortOrder(SAMFileHeader.SortOrder.coordinate);
final List<SAMFileReader> readerList = new ArrayList<SAMFileReader>();
readerList.add(samReader);
readerList.add(samReader2);
final List<SAMFileHeader> headerList = new ArrayList<SAMFileHeader>();
headerList.add(samReader.getFileHeader());
headerList.add(samReader2.getFileHeader());
final SamFileHeaderMerger fileHeaderMerger = new SamFileHeaderMerger(SAMFileHeader.SortOrder.coordinate, headerList, false);
final MergingSamRecordIterator iterator = new MergingSamRecordIterator(fileHeaderMerger, readerList, false);
int i = 0;
// This is the correct order for start bases. The first two are on chr20, the next three on chr22
final int[] startBasesInOrder = {28833, 30000, 28834, 28835, 28835};
while (iterator.hasNext()) {
final SAMRecord rec = iterator.next();
System.out.println(rec.format());
Assert.assertEquals(rec.getAlignmentStart(), startBasesInOrder[i]);
i++;
}
samReader.close();
}
@Test
public void testVanillaReadOrderMultiIterator() throws Exception {
final SAMRecordSetBuilder builder1 = new SAMRecordSetBuilder(false, SAMFileHeader.SortOrder.queryname);
builder1.addFrag("a", 20, 28833, false); // ok
builder1.addFrag("e", 19, 28834, false); // ok
final SAMFileReader samReader = builder1.getSamReader();
final SAMRecordSetBuilder builder2 = new SAMRecordSetBuilder(false, SAMFileHeader.SortOrder.queryname);
builder2.addFrag("b", 20, 30000, false); // ok
builder2.addFrag("c", 22, 28835, false); // ok
builder2.addFrag("d", 20, 28835, false); // ok
final SAMFileReader samReader2 = builder2.getSamReader();
final List<SAMFileReader> readerList = new ArrayList<SAMFileReader>();
readerList.add(samReader);
readerList.add(samReader2);
final List<SAMFileHeader> headerList = new ArrayList<SAMFileHeader>();
headerList.add(samReader.getFileHeader());
headerList.add(samReader2.getFileHeader());
final SamFileHeaderMerger fileHeaderMerger = new SamFileHeaderMerger(SAMFileHeader.SortOrder.queryname, headerList, false);
final MergingSamRecordIterator iterator = new MergingSamRecordIterator(fileHeaderMerger, readerList, false);
int i = 0;
// This is the correct order for start bases. The first two are on chr20, the next three on chr22
final String[] orderedReadNames = {"a", "b", "c", "d", "e"};
while (iterator.hasNext()) {
final SAMRecord rec = iterator.next();
System.out.println(rec.getReadName());
Assert.assertEquals(rec.getReadName(), orderedReadNames[i]);
i++;
}
samReader.close();
}
@Test
public void testVanillaUnsortedMultiIterator() throws Exception {
final SAMRecordSetBuilder builder1 = new SAMRecordSetBuilder(false, SAMFileHeader.SortOrder.unsorted);
builder1.addFrag("b", 20, 28833, false); // ok
builder1.addFrag("a", 19, 28834, false); // ok
final SAMFileReader samReader = builder1.getSamReader();
final SAMRecordSetBuilder builder2 = new SAMRecordSetBuilder(false, SAMFileHeader.SortOrder.unsorted);
builder2.addFrag("d", 20, 30000, false); // ok
builder2.addFrag("e", 22, 28835, false); // ok
builder2.addFrag("c", 20, 28835, false); // ok
final SAMFileReader samReader2 = builder2.getSamReader();
final List<SAMFileReader> readerList = new ArrayList<SAMFileReader>();
readerList.add(samReader);
readerList.add(samReader2);
final List<SAMFileHeader> headerList = new ArrayList<SAMFileHeader>();
headerList.add(samReader.getFileHeader());
headerList.add(samReader2.getFileHeader());
final SamFileHeaderMerger fileHeaderMerger = new SamFileHeaderMerger(SAMFileHeader.SortOrder.unsorted, headerList, false);
final MergingSamRecordIterator iterator = new MergingSamRecordIterator(fileHeaderMerger, readerList, false);
int i = 0;
// With unsorted option there is no garantee that order of the names to come back from the iterator
final String[] readNames = {"b", "a", "d", "e", "c"};
while (iterator.hasNext()) {
final SAMRecord rec = iterator.next();
System.out.println(rec.getReadName());
i++;
}
Assert.assertEquals(i, readNames.length);
samReader.close();
}
@Test(expectedExceptions = SequenceUtil.SequenceListsDifferException.class)
public void testConflictingHeaders() throws Exception {
final SAMRecordSetBuilder builder1 = new SAMRecordSetBuilder();
builder1.addFrag("read_28833_29006_6945", 20, 28833, false); // ok
builder1.addFrag("read_28701_28881_323b", 22, 28834, false); // ok
final SAMFileReader samReader = builder1.getSamReader();
samReader.getFileHeader().setSortOrder(SAMFileHeader.SortOrder.coordinate);
final SAMRecordSetBuilder builder2 = new SAMRecordSetBuilder();
builder2.addFrag("read_28833_29006_6945", 20, 30000, false); // ok
builder2.addFrag("read_28701_28881_323b", 22, 28835, false); // ok
builder2.addFrag("read_28701_28881_323c", 22, 28835, false); // ok
final SAMFileReader samReader2 = builder2.getSamReader();
samReader2.getFileHeader().setSortOrder(SAMFileHeader.SortOrder.coordinate);
//Change one of the header so they are no longer compatible
final SAMSequenceRecord sRec = new SAMSequenceRecord("BADSEQ", 0);
samReader2.getFileHeader().addSequence(sRec);
final List<SAMFileReader> readerList = new ArrayList<SAMFileReader>();
readerList.add(samReader);
readerList.add(samReader2);
final List<SAMFileHeader> headerList = new ArrayList<SAMFileHeader>();
headerList.add(samReader.getFileHeader());
headerList.add(samReader2.getFileHeader());
final SamFileHeaderMerger samFileHeaderMerger = new SamFileHeaderMerger(SAMFileHeader.SortOrder.coordinate, headerList, false);
new MergingSamRecordIterator(samFileHeaderMerger, readerList, false);
Assert.fail("This method should throw exception before getting to this point");
}
@Test(expectedExceptions = SAMException.class)
public void filesNotSortedCorrectly() throws Exception {
final SAMRecordSetBuilder builder1 = new SAMRecordSetBuilder(false, SAMFileHeader.SortOrder.coordinate);
builder1.addFrag("read_28833_29006_6945", 20, 28833, false); // ok
builder1.addFrag("read_28701_28881_323b", 22, 28834, false); // ok
final SAMFileReader samReader = builder1.getSamReader();
final SAMRecordSetBuilder builder2 = new SAMRecordSetBuilder(false, SAMFileHeader.SortOrder.unsorted);
final SAMFileReader samReader2 = builder2.getSamReader();
builder2.addFrag("read_28701_28881_323b", 22, 28835, false); // ok
builder2.addFrag("read_28833_29006_6945", 20, 30000, false); // ok
builder2.addFrag("read_28701_28881_323c", 22, 28835, false); // ok
final List<SAMFileReader> readerList = new ArrayList<SAMFileReader>();
readerList.add(samReader);
readerList.add(samReader2);
final List<SAMFileHeader> headerList = new ArrayList<SAMFileHeader>();
headerList.add(samReader.getFileHeader());
headerList.add(samReader2.getFileHeader());
final SamFileHeaderMerger fileHeaderMerger = new SamFileHeaderMerger(SAMFileHeader.SortOrder.coordinate, headerList, false);
new MergingSamRecordIterator(fileHeaderMerger, readerList, false);
Assert.fail("This method should throw exception before getting to this point");
}
@Test
public void testHeaderCommentMerge() throws Exception {
final String[] comments1 = {"@CO\tHi, Mom!", "@CO\tHi, Dad!"};
final String[] comments2 = {"@CO\tHello, World!", "@CO\tGoodbye, Cruel World!"};
final Set<String> bothComments = new HashSet<String>();
bothComments.addAll(Arrays.asList(comments1));
bothComments.addAll(Arrays.asList(comments2));
final SAMRecordSetBuilder builder1 = new SAMRecordSetBuilder(false, SAMFileHeader.SortOrder.coordinate);
SAMFileHeader header = builder1.getHeader();
for (final String comment : comments1) {
header.addComment(comment);
}
final SAMRecordSetBuilder builder2 = new SAMRecordSetBuilder(false, SAMFileHeader.SortOrder.coordinate);
header = builder2.getHeader();
for (final String comment : comments2) {
header.addComment(comment);
}
final SamFileHeaderMerger merger = new SamFileHeaderMerger(SAMFileHeader.SortOrder.coordinate,
Arrays.asList(builder1.getSamReader().getFileHeader(), builder2.getSamReader().getFileHeader()), false);
final List<String> mergedComments = merger.getMergedHeader().getComments();
Assert.assertEquals(mergedComments.size(), bothComments.size());
for (final String comment : mergedComments) {
Assert.assertTrue(bothComments.contains(comment));
}
}
}