Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Public method for CRAMIntervalIterator for overlapping intervals #1120

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
43 changes: 30 additions & 13 deletions src/main/java/htsjdk/samtools/CRAMFileReader.java
Expand Up @@ -466,6 +466,32 @@ void enableFileSource(final SamReader reader, final boolean enabled) {
iterator.setFileSource(enabled ? reader : null);
}

/**
* Prepare to iterate through SAMRecords that match the intersection of the given intervals and chunk boundaries.
* @param intervals the intervals to restrict reads to
* @param contained if <code>true</code>, return records that are strictly
* contained in the intervals, otherwise return records that overlap
* @param filePointers file pointer pairs corresponding to chunk boundaries for the
* intervals
*/
public CloseableIterator<SAMRecord> createIndexIterator(final QueryInterval[] intervals,
final boolean contained,
final long[] filePointers) {
return new CRAMIntervalIterator(intervals, contained, filePointers);
}

// convert queries -> merged BAMFileSpan -> coordinate array
private static long[] coordinatesFromQueryIntervals(BAMIndex index, QueryInterval[] queries) {
ArrayList<BAMFileSpan> spanList = new ArrayList<>(1);
Arrays.asList(queries).forEach(qi -> spanList.add(index.getSpanOverlapping(qi.referenceIndex, qi.start, qi.end)));
BAMFileSpan spanArray[] = new BAMFileSpan[spanList.size()];
for (int i = 0; i < spanList.size(); i++) {
spanArray[i] = spanList.get(i);
}

return BAMFileSpan.merge(spanArray).toCoordinateArray();
}

private class CRAMIntervalIterator extends BAMQueryMultipleIntervalsIteratorFilter
implements CloseableIterator<SAMRecord> {

Expand All @@ -475,9 +501,12 @@ private class CRAMIntervalIterator extends BAMQueryMultipleIntervalsIteratorFilt
SAMRecord nextRec = null;

public CRAMIntervalIterator(final QueryInterval[] queries, final boolean contained) {
this(queries, contained, coordinatesFromQueryIntervals(getIndex(), queries));
}

public CRAMIntervalIterator(final QueryInterval[] queries, final boolean contained, final long[] coordinates) {
super(queries, contained);

long[] coordinates = coordinatesFromQueryIntervals(getIndex(), queries);
if (coordinates != null && coordinates.length != 0) {
try {
unfilteredIterator = new CRAMIterator(
Expand All @@ -493,18 +522,6 @@ public CRAMIntervalIterator(final QueryInterval[] queries, final boolean contain
}
}

// convert queries -> merged BAMFileSpan -> coordinate array
private long[] coordinatesFromQueryIntervals(BAMIndex index, QueryInterval[] queries) {
ArrayList<BAMFileSpan> spanList = new ArrayList<>(1);
Arrays.asList(queries).forEach(qi -> spanList.add(mIndex.getSpanOverlapping(qi.referenceIndex, qi.start, qi.end)));
BAMFileSpan spanArray[] = new BAMFileSpan[spanList.size()];
for (int i = 0; i < spanList.size(); i++) {
spanArray[i] = spanList.get(i);
}

return BAMFileSpan.merge(spanArray).toCoordinateArray();
}

@Override
public void close() {
if (unfilteredIterator != null) {
Expand Down
23 changes: 23 additions & 0 deletions src/test/java/htsjdk/samtools/CRAMFileCRAIIndexTest.java
Expand Up @@ -304,6 +304,29 @@ public void testQueryInterval() throws IOException {
reader.close();
}

@Test
public void testQueryIntervalWithFilePointers() throws IOException {
CRAMFileReader reader = new CRAMFileReader(
new ByteArraySeekableStream(cramBytes),
new ByteArraySeekableStream(craiBytes),
source,
ValidationStringency.STRICT);
QueryInterval[] query = new QueryInterval[]{new QueryInterval(0, 1519, 1520), new QueryInterval(1, 470535, 470536)};
BAMFileSpan fileSpan = BAMFileReader.getFileSpan(query, reader.getIndex());
final CloseableIterator<SAMRecord> iterator = reader.createIndexIterator(query, false, fileSpan.toCoordinateArray());
Assert.assertTrue(iterator.hasNext());
SAMRecord r1 = iterator.next();
Assert.assertEquals(r1.getReadName(), "3968040");

Assert.assertTrue(iterator.hasNext());
SAMRecord r2 = iterator.next();
Assert.assertEquals(r2.getReadName(), "140419");

Assert.assertFalse(iterator.hasNext());
iterator.close();
reader.close();
}

@BeforeTest
public void prepare() throws IOException {
Log.setGlobalLogLevel(Log.LogLevel.ERROR);
Expand Down