Skip to content

Commit 7f76630

Browse files
committed
Make PileupBuilder.includeMapPositionsOutsideFrInsert intuitively correct
1 parent 3a74fd2 commit 7f76630

File tree

3 files changed

+50
-11
lines changed

3 files changed

+50
-11
lines changed

src/main/scala/com/fulcrumgenomics/bam/pileup/PileupBuilder.scala

+6-9
Original file line numberDiff line numberDiff line change
@@ -116,14 +116,11 @@ object PileupBuilder {
116116
)
117117
}
118118

119-
/** Returns true if <rec> is in a mapped FR pair but the position <pos> is outside the insert coordinates of <rec>.
120-
* Returns false if <rec> is in a mapped FR pair and the position <pos> is inside the insert coordinates of <rec> or
121-
* <rec> is not in a mapped FR pair.
122-
*/
123-
private def positionIsOutsideFrInsert(rec: SamRecord, refIndex: Int, pos: Int): Boolean = {
124-
rec.isFrPair && {
119+
/** Returns true if <rec> is in a mapped FR pair and the position <pos> is inside the insert coordinates of <rec>. */
120+
private def positionIsInsideFrInsert(rec: SamRecord, refIndex: Int, pos: Int): Boolean = {
121+
refIndex == rec.refIndex && rec.isFrPair && {
125122
val (start, end) = Bams.insertCoordinates(rec)
126-
rec.refIndex == refIndex && pos >= start && pos <= end
123+
pos >= start && pos <= end
127124
}
128125
}
129126

@@ -200,8 +197,8 @@ trait PileupBuilder extends PileupParameters {
200197
if (compare) compare = this.acceptRecord(rec)
201198
if (compare) compare = rec.end >= pos
202199
if (compare) compare = rec.start <= pos || PileupBuilder.startsWithInsertion(rec)
203-
if (compare) compare = if (!includeMapPositionsOutsideFrInsert && rec.isFrPair) {
204-
PileupBuilder.positionIsOutsideFrInsert(rec, refIndex = refIndex, pos = pos)
200+
if (compare) compare = if (rec.paired && !includeMapPositionsOutsideFrInsert) {
201+
PileupBuilder.positionIsInsideFrInsert(rec, refIndex = refIndex, pos = pos)
205202
} else { compare }
206203
compare
207204
}

src/main/scala/com/fulcrumgenomics/testing/SamBuilder.scala

+5-2
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,17 @@ package com.fulcrumgenomics.testing
2727
import java.nio.file.Files
2828
import java.text.DecimalFormat
2929
import java.util.concurrent.atomic.AtomicLong
30-
3130
import com.fulcrumgenomics.FgBioDef._
3231
import com.fulcrumgenomics.alignment.Cigar
32+
import com.fulcrumgenomics.commons.CommonsDef.IteratorToJavaCollectionsAdapter
3333
import com.fulcrumgenomics.bam.api.SamRecord.{MissingBases, MissingQuals}
3434
import com.fulcrumgenomics.bam.api.{SamOrder, SamRecord, SamSource, SamWriter}
3535
import com.fulcrumgenomics.fasta.{SequenceDictionary, SequenceMetadata}
3636
import com.fulcrumgenomics.testing.SamBuilder._
37+
import htsjdk.samtools.SamPairUtil.PairOrientation
3738
import htsjdk.samtools._
3839

40+
import java.util
3941
import scala.collection.mutable.ArrayBuffer
4042
import scala.util.Random
4143

@@ -173,7 +175,8 @@ class SamBuilder(val readLength: Int=100,
173175
r2("RG") = this.rg.getId
174176
attrs.foreach { case (key, value) => r2(key) = value }
175177

176-
SamPairUtil.setMateInfo(r1.asSam, r2.asSam, true)
178+
val orientations = util.Arrays.asList(PairOrientation.FR, PairOrientation.RF, PairOrientation.TANDEM)
179+
SamPairUtil.setProperPairAndMateInfo(r1.asSam, r2.asSam, orientations, true)
177180
val recs = Seq(r1, r2)
178181
this.records ++= recs
179182
recs

src/test/scala/com/fulcrumgenomics/bam/pileup/PileupBuilderTest.scala

+39
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,26 @@ class PileupBuilderTest extends UnitSpec {
289289
piler.safelyClose()
290290
}
291291

292+
it should "not filter out single-end records when we are removing records outside the insert of FR pairs" in {
293+
val builder = new SamBuilder(readLength = ReadLength, sd = Some(TestSequenceDictionary), sort = Some(Coordinate))
294+
295+
builder.addFrag(name = "q1", contig = Chr1Index, start = 100)
296+
297+
val source = builder.toSource
298+
val piler = PileupBuilder(
299+
source,
300+
accessPattern = accessPattern,
301+
mappedPairsOnly = false,
302+
includeMapPositionsOutsideFrInsert = true
303+
)
304+
305+
piler.pileup(Chr1, 100).depth shouldBe 1
306+
piler.pileup(Chr1, 100 + ReadLength - 1).depth shouldBe 1
307+
308+
source.safelyClose()
309+
piler.safelyClose()
310+
}
311+
292312
it should "filter out records where a position is outside the insert for an FR pair" in {
293313
val builder = new SamBuilder(readLength = ReadLength, sd = Some(TestSequenceDictionary), sort = Some(Coordinate))
294314

@@ -323,6 +343,23 @@ class PileupBuilderTest extends UnitSpec {
323343
piler.safelyClose()
324344
}
325345

346+
it should "exclude records that appear to be in an FR pair but are on different chromosomes" in {
347+
val builder = new SamBuilder(readLength = ReadLength, sd = Some(TestSequenceDictionary), sort = Some(Coordinate))
348+
349+
builder.addPair(name = "q1", contig = Chr1Index, contig2 = Some(Chr2Index), start1 = 100, start2 = 125)
350+
351+
val source = builder.toSource
352+
val piler = PileupBuilder(source, accessPattern = accessPattern, includeMapPositionsOutsideFrInsert = false)
353+
354+
piler.pileup(Chr1, 100).depth shouldBe 0
355+
piler.pileup(Chr1, 101).depth shouldBe 0
356+
piler.pileup(Chr1, 100 + ReadLength - 1).depth shouldBe 0
357+
piler.pileup(Chr1, 101 + ReadLength - 1).depth shouldBe 0
358+
359+
source.safelyClose()
360+
piler.safelyClose()
361+
}
362+
326363
it should "not filter out records where a position is outside what might look like an 'insert' for a non-FR pair" in {
327364
val builder = new SamBuilder(readLength = ReadLength, sd = Some(TestSequenceDictionary), sort = Some(Coordinate))
328365

@@ -340,6 +377,8 @@ class PileupBuilderTest extends UnitSpec {
340377
piler.safelyClose()
341378
}
342379

380+
//////
381+
343382
it should "filter out records and entries with custom filters" in {
344383
val builder = new SamBuilder(readLength = ReadLength, sd = Some(TestSequenceDictionary), sort = Some(Coordinate))
345384

0 commit comments

Comments
 (0)