|
24 | 24 |
|
25 | 25 | package com.fulcrumgenomics.bam.api
|
26 | 26 |
|
| 27 | +import com.fulcrumgenomics.bam.{Bams, Supplementary} |
27 | 28 | import com.fulcrumgenomics.umi.ConsensusTags
|
28 | 29 | import htsjdk.samtools.SAMFileHeader.{GroupOrder, SortOrder}
|
29 | 30 | import htsjdk.samtools.util.Murmur3
|
30 | 31 | import htsjdk.samtools.{SAMFileHeader, SAMUtils}
|
31 | 32 | import org.apache.commons.math3.genetics.RandomKey
|
32 | 33 |
|
| 34 | +import scala.reflect.runtime.universe.Template |
| 35 | + |
33 | 36 |
|
34 | 37 | /** Trait for specifying BAM orderings. */
|
35 | 38 | sealed trait SamOrder extends Product {
|
@@ -175,24 +178,50 @@ object SamOrder {
|
175 | 178 | override val groupOrder: GroupOrder = GroupOrder.query
|
176 | 179 | override val subSort: Option[String] = Some("template-coordinate")
|
177 | 180 | override val sortkey: SamRecord => A = rec => {
|
178 |
| - val readChrom = if (rec.unmapped) Int.MaxValue else rec.refIndex |
179 |
| - val mateChrom = if (rec.unpaired || rec.mateUnmapped) Int.MaxValue else rec.mateRefIndex |
180 |
| - val readNeg = rec.negativeStrand |
181 |
| - val mateNeg = if (rec.paired) rec.mateNegativeStrand else false |
182 |
| - val readPos = if (rec.unmapped) Int.MaxValue else if (readNeg) rec.unclippedEnd else rec.unclippedStart |
183 |
| - val matePos = if (rec.unpaired || rec.mateUnmapped) Int.MaxValue else if (mateNeg) SAMUtils.getMateUnclippedEnd(rec.asSam) else SAMUtils.getMateUnclippedStart(rec.asSam) |
184 |
| - val lib = Option(rec.readGroup).flatMap(rg => Option(rg.getLibrary)).getOrElse("Unknown") |
185 |
| - val mid = rec.get[String](ConsensusTags.MolecularId).map { m => |
186 |
| - val index: Int = m.lastIndexOf('/') |
187 |
| - if (index >= 0) m.substring(0, index) else m |
188 |
| - }.getOrElse("") |
189 |
| - |
190 |
| - if (readChrom < mateChrom || (readChrom == mateChrom && readPos < matePos) || |
191 |
| - (readChrom == mateChrom && readPos == matePos && !readNeg)) { |
192 |
| - TemplateCoordinateKey(readChrom, mateChrom, readPos, matePos, readNeg, mateNeg, lib, mid, rec.name, false) |
193 |
| - } |
194 |
| - else { |
195 |
| - TemplateCoordinateKey(mateChrom, readChrom, matePos, readPos, mateNeg, readNeg, lib, mid, rec.name, true) |
| 181 | + // For non-secondary/non-supplementary alignments, use the info in the record. For secondary and supplementary |
| 182 | + // alignments, use the info in the pa/pm tags. |
| 183 | + if (!rec.secondary && !rec.supplementary) { |
| 184 | + val readChrom = if (rec.unmapped) Int.MaxValue else rec.refIndex |
| 185 | + val mateChrom = if (rec.unpaired || rec.mateUnmapped) Int.MaxValue else rec.mateRefIndex |
| 186 | + val readNeg = rec.negativeStrand |
| 187 | + val mateNeg = if (rec.paired) rec.mateNegativeStrand else false |
| 188 | + val readPos = if (rec.unmapped) Int.MaxValue else if (readNeg) rec.unclippedEnd else rec.unclippedStart |
| 189 | + val matePos = if (rec.unpaired || rec.mateUnmapped) Int.MaxValue else if (mateNeg) SAMUtils.getMateUnclippedEnd(rec.asSam) else SAMUtils.getMateUnclippedStart(rec.asSam) |
| 190 | + val lib = Option(rec.readGroup).flatMap(rg => Option(rg.getLibrary)).getOrElse("Unknown") |
| 191 | + val mid = rec.get[String](ConsensusTags.MolecularId).map { m => |
| 192 | + val index: Int = m.lastIndexOf('/') |
| 193 | + if (index >= 0) m.substring(0, index) else m |
| 194 | + }.getOrElse("") |
| 195 | + |
| 196 | + if (readChrom < mateChrom || (readChrom == mateChrom && readPos < matePos) || |
| 197 | + (readChrom == mateChrom && readPos == matePos && !readNeg)) { |
| 198 | + TemplateCoordinateKey(readChrom, mateChrom, readPos, matePos, readNeg, mateNeg, lib, mid, rec.name, false) |
| 199 | + } |
| 200 | + else { |
| 201 | + TemplateCoordinateKey(mateChrom, readChrom, matePos, readPos, mateNeg, readNeg, lib, mid, rec.name, true) |
| 202 | + } |
| 203 | + } else { |
| 204 | + val primary = Supplementary(rec[String]("rp")) |
| 205 | + val mate = Supplementary(rec[String]("mp")) |
| 206 | + val readChrom = if (rec.unmapped) Int.MaxValue else primary.refIndex(rec.header) |
| 207 | + val mateChrom = if (rec.unpaired || rec.mateUnmapped) Int.MaxValue else mate.refIndex(rec.header) |
| 208 | + val readNeg = primary.negativeStrand |
| 209 | + val mateNeg = if (rec.paired) mate.negativeStrand else false |
| 210 | + val readPos = if (rec.unmapped) Int.MaxValue else if (readNeg) primary.unclippedEnd else primary.unclippedStart |
| 211 | + val matePos = if (rec.unpaired || rec.mateUnmapped) Int.MaxValue else if (mateNeg) mate.unclippedEnd else mate.unclippedStart |
| 212 | + val lib = Option(rec.readGroup).flatMap(rg => Option(rg.getLibrary)).getOrElse("Unknown") |
| 213 | + val mid = rec.get[String](ConsensusTags.MolecularId).map { m => |
| 214 | + val index: Int = m.lastIndexOf('/') |
| 215 | + if (index >= 0) m.substring(0, index) else m |
| 216 | + }.getOrElse("") |
| 217 | + |
| 218 | + if (readChrom < mateChrom || (readChrom == mateChrom && readPos < matePos) || |
| 219 | + (readChrom == mateChrom && readPos == matePos && !readNeg)) { |
| 220 | + TemplateCoordinateKey(readChrom, mateChrom, readPos, matePos, readNeg, mateNeg, lib, mid, rec.name, false) |
| 221 | + } |
| 222 | + else { |
| 223 | + TemplateCoordinateKey(mateChrom, readChrom, matePos, readPos, mateNeg, readNeg, lib, mid, rec.name, true) |
| 224 | + } |
196 | 225 | }
|
197 | 226 | }
|
198 | 227 | }
|
|
0 commit comments