diff --git a/adam-core/src/main/scala/edu/berkeley/cs/amplab/adam/rich/RichADAMRecord.scala b/adam-core/src/main/scala/edu/berkeley/cs/amplab/adam/rich/RichADAMRecord.scala index ebfd489125..452c7c75c4 100644 --- a/adam-core/src/main/scala/edu/berkeley/cs/amplab/adam/rich/RichADAMRecord.scala +++ b/adam-core/src/main/scala/edu/berkeley/cs/amplab/adam/rich/RichADAMRecord.scala @@ -148,7 +148,7 @@ class RichADAMRecord(record: ADAMRecord) { CigarOperator.EQ | CigarOperator.S => { val positions = Range(posAtCigar.toInt, posAtCigar.toInt + elem.getLength) - (positions.last, basePositions ++ positions.map(t => Some(t.toLong))) + (positions.last + 1, basePositions ++ positions.map(t => Some(t.toLong))) } case CigarOperator.H => { runningPos /* do nothing */ diff --git a/adam-core/src/test/scala/edu/berkeley/cs/amplab/adam/rich/RichADAMRecordSuite.scala b/adam-core/src/test/scala/edu/berkeley/cs/amplab/adam/rich/RichADAMRecordSuite.scala index 33fdbb1bf0..dd273ab78c 100644 --- a/adam-core/src/test/scala/edu/berkeley/cs/amplab/adam/rich/RichADAMRecordSuite.scala +++ b/adam-core/src/test/scala/edu/berkeley/cs/amplab/adam/rich/RichADAMRecordSuite.scala @@ -41,6 +41,19 @@ class RichADAMRecordSuite extends FunSuite { assert(recordWithHardClipping.unclippedEnd == Some(20L)) } + test( "Reference End Position") + { + val unmappedRead = ADAMRecord.newBuilder().setReadMapped(false).setStart(0).setCigar("10M").build() + val recordWithoutClipping = ADAMRecord.newBuilder().setReadMapped(true).setCigar("10M").setStart(10).build() + val recordWithClipping = ADAMRecord.newBuilder().setReadMapped(true).setCigar("8M2S").setStart(10).build() + val recordWithHardClipping = ADAMRecord.newBuilder().setReadMapped(true).setCigar("6M2S2H").setStart(10).build() + assert(unmappedRead.end == None) + assert(recordWithoutClipping.end == Some(20L)) + assert(recordWithClipping.end == Some(18L)) + assert(recordWithHardClipping.end == Some(16L)) + + } + test("Illumina Optics") { val nonIlluminaRecord = ADAMRecord.newBuilder().setReadName("THISISNOTILLUMINA").build() assert(nonIlluminaRecord.illuminaOptics == None) @@ -54,4 +67,54 @@ class RichADAMRecordSuite extends FunSuite { } } + test("Cigar Clipping Sequence") { + val softClippedRead = ADAMRecord.newBuilder().setReadMapped(true).setStart(100).setCigar("10S90M").build() + assert( softClippedRead.referencePositions(0) == Some(90L)) + + + } + + test("Reference Positions") { + + val hardClippedRead = ADAMRecord.newBuilder().setReadMapped(true).setStart(1000).setCigar("90M10H").build() + assert( hardClippedRead.referencePositions.length == 90) + assert( hardClippedRead.referencePositions(0) == Some(1000L)) + + val softClippedRead = ADAMRecord.newBuilder().setReadMapped(true).setStart(1000).setCigar("10S90M").build() + assert( softClippedRead.referencePositions.length == 100) + assert( softClippedRead.referencePositions(0) == Some(990L)) + assert( softClippedRead.referencePositions(10) == Some(1000L)) + + val doubleMatchNonsenseRead = ADAMRecord.newBuilder().setReadMapped(true).setStart(1000).setCigar("10M10M").build() + Range(0,20).foreach( i => assert( doubleMatchNonsenseRead.referencePositions(i) == Some(1000 + i) )) + + val deletionRead = ADAMRecord.newBuilder().setReadMapped(true).setStart(1000).setCigar("5M5D10M").build() + assert( deletionRead.referencePositions.length == 15) + assert( deletionRead.referencePositions(0) == Some(1000L)) + assert( deletionRead.referencePositions(5) == Some(1010L)) + + val insertionRead = ADAMRecord.newBuilder().setReadMapped(true).setStart(1000).setCigar("10M2I10M").build() + assert( insertionRead.referencePositions.length == 22) + assert( insertionRead.referencePositions(0) == Some(1000L)) + assert( insertionRead.referencePositions(10) == None) + assert( insertionRead.referencePositions(12) == Some(1010L)) + + val indelRead = ADAMRecord.newBuilder().setReadMapped(true).setStart(1000).setCigar("10M3D10M2I").build() + assert( indelRead.referencePositions.length == 22) + assert( indelRead.referencePositions(0) == Some(1000L)) + assert( indelRead.referencePositions(10) == Some(1013L)) + assert( indelRead.referencePositions(20) == None ) + + val hg00096read = ADAMRecord.newBuilder().setReadMapped(true).setStart(1000).setCigar("1S28M1D32M1I15M1D23M").build() + assert( hg00096read.referencePositions.length == 100) + assert( hg00096read.referencePositions(0) == Some(999L)) + assert( hg00096read.referencePositions(1) == Some(1000L)) + assert( hg00096read.referencePositions(29) == Some(1029L) ) + assert( hg00096read.referencePositions(61) == None ) + assert( hg00096read.referencePositions(62) == Some(1061L) ) + assert( hg00096read.referencePositions(78) == Some(1078L) ) + assert( hg00096read.referencePositions(99) == Some(1099L) ) + + } + }