diff --git a/src/main/scala/com/fulcrumgenomics/bam/api/SamSource.scala b/src/main/scala/com/fulcrumgenomics/bam/api/SamSource.scala index c9ea7703e..32852cebd 100644 --- a/src/main/scala/com/fulcrumgenomics/bam/api/SamSource.scala +++ b/src/main/scala/com/fulcrumgenomics/bam/api/SamSource.scala @@ -91,9 +91,16 @@ class SamSource private(private val reader: SamReader) extends View[SamRecord] w /** Returns an iterator over all the records in the source. */ override def iterator: SamIterator = new SamIterator(reader.getFileHeader, reader.iterator()) + private def newQueryInterval(region: Locatable): QueryInterval = { + val contig = dict(region.getContig) + val start = Math.max(region.getStart, 1); + val end = Math.min(region.getEnd, contig.length) + new QueryInterval(contig.index, start, end) + } + /** Returns an iterator over the records in the regions provided. */ def query(regions: IterableOnce[Locatable], queryType: QueryType = QueryType.Overlapping): SamIterator = { - val queries = QueryInterval.optimizeIntervals(regions.iterator.map(l => new QueryInterval(dict(l.getContig).index, l.getStart, l.getEnd)).toArray) + val queries = QueryInterval.optimizeIntervals(regions.iterator.map(l => newQueryInterval(l)).toArray) val contained = queryType == QueryType.Contained new SamIterator(header, reader.query(queries, contained)) } diff --git a/src/test/scala/com/fulcrumgenomics/bam/api/SamIoTest.scala b/src/test/scala/com/fulcrumgenomics/bam/api/SamIoTest.scala index c6c0fb9b1..d1b129b1e 100644 --- a/src/test/scala/com/fulcrumgenomics/bam/api/SamIoTest.scala +++ b/src/test/scala/com/fulcrumgenomics/bam/api/SamIoTest.scala @@ -28,6 +28,7 @@ import java.nio.file.Files import java.util.concurrent.{Callable, Executors, TimeUnit} import com.fulcrumgenomics.FgBioDef._ +import com.fulcrumgenomics.bam.api.QueryType.QueryType import com.fulcrumgenomics.fasta.{SequenceDictionary, SequenceMetadata} import com.fulcrumgenomics.testing.{SamBuilder, UnitSpec} import com.fulcrumgenomics.util.Io @@ -164,4 +165,28 @@ class SamIoTest extends UnitSpec { filterCount shouldBe 10 mapCount shouldBe 10 } + + "SamSource.query" should "" in { + val queryType = QueryType.Overlapping + val builder = new SamBuilder(readLength=10, baseQuality=20, sort=Some(SamOrder.Coordinate)) + Range(0, 10).foreach { _ => builder.addFrag(start=100) } + val source = builder.toSource + + // test a query before the contig start + source.query("chr1", 0, 1000, queryType).length shouldBe 10 + source.query("chr1", -100, 1000, queryType).length shouldBe 10 + + // test a query after the contig end + val contigEnd = builder.dict("chr1").length + source.query("chr1", 100, contigEnd+1, queryType).length shouldBe 10 + source.query("chr1", 100, contigEnd+100, queryType).length shouldBe 10 + + // test a query both before and after the contig start and end respectively + source.query("chr1", -100, contigEnd+100, queryType).length shouldBe 10 + + // at the start and end + source.query("chr1", 1, 1000, queryType).length shouldBe 10 + source.query("chr1", 100, contigEnd, queryType).length shouldBe 10 + source.query("chr1", 1, contigEnd, queryType).length shouldBe 10 + } }