From 85f969187cfca7ea03ca9f3a0d7276ede0702bb7 Mon Sep 17 00:00:00 2001 From: znorgaard Date: Mon, 1 Jul 2024 15:54:03 -0700 Subject: [PATCH] feat: add isConsensus method --- .../com/fulcrumgenomics/bam/api/SamRecord.scala | 5 +++++ .../fulcrumgenomics/bam/api/SamRecordTest.scala | 14 ++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/main/scala/com/fulcrumgenomics/bam/api/SamRecord.scala b/src/main/scala/com/fulcrumgenomics/bam/api/SamRecord.scala index cf05b54c6..40fce0b64 100644 --- a/src/main/scala/com/fulcrumgenomics/bam/api/SamRecord.scala +++ b/src/main/scala/com/fulcrumgenomics/bam/api/SamRecord.scala @@ -27,6 +27,7 @@ package com.fulcrumgenomics.bam.api import com.fulcrumgenomics.FgBioDef._ import com.fulcrumgenomics.alignment.Cigar +import com.fulcrumgenomics.umi.ConsensusTags.PerRead.AllPerReadTags import htsjdk.samtools import htsjdk.samtools.SamPairUtil.PairOrientation import htsjdk.samtools._ @@ -269,6 +270,10 @@ trait SamRecord { SamPairUtil.getPairOrientation(this) == PairOrientation.FR } + def isConsensus: Boolean = { + AllPerReadTags.exists(this.contains) + } + /** Clone method that does a "reasonably deep" clone. The bases and quals are cloned as is the attributes map, * though not the values in the attributes map. */ override def clone(): SamRecord = { diff --git a/src/test/scala/com/fulcrumgenomics/bam/api/SamRecordTest.scala b/src/test/scala/com/fulcrumgenomics/bam/api/SamRecordTest.scala index 38251e0c4..82f34e940 100644 --- a/src/test/scala/com/fulcrumgenomics/bam/api/SamRecordTest.scala +++ b/src/test/scala/com/fulcrumgenomics/bam/api/SamRecordTest.scala @@ -27,6 +27,7 @@ package com.fulcrumgenomics.bam.api import com.fulcrumgenomics.alignment.Cigar import com.fulcrumgenomics.testing.SamBuilder.{Minus, Plus} import com.fulcrumgenomics.testing.{SamBuilder, UnitSpec} +import com.fulcrumgenomics.umi.ConsensusTags.PerRead.AllPerReadTags import htsjdk.samtools.TextCigarCodec import org.scalatest.OptionValues @@ -289,4 +290,17 @@ class SamRecordTest extends UnitSpec with OptionValues { rec1.matesOverlap shouldBe None // Mate's start is not enclosed by rec, and mate's end cannot be determined rec2.matesOverlap.value shouldBe true // Mate's start is enclosed by rec, regardless of where mate end is } + + "SamRecord.isConsensus" should "return false for reads without consensus tags" in { + val builder = new SamBuilder(sort=Some(SamOrder.Coordinate), readLength=10, baseQuality=20) + builder.addFrag(start=100).exists(_.isConsensus) shouldBe false + builder.addPair(start1=100, start2=100, unmapped2=true).exists(_.isConsensus) shouldBe false + } + + it should "return true for reads with consensus tags" in { + val builder = new SamBuilder(sort=Some(SamOrder.Coordinate), readLength=10, baseQuality=20) + AllPerReadTags.forall( + tag => builder.addFrag(start=10, attrs=Map(tag -> 123)).exists(_.isConsensus) + ) shouldBe true + } }