use crate::read_filter::ReadFilter;
use rust_htslib::bam::{pileup::Alignment, record::Record};
use strum::EnumString;
use std::cmp::Ordering;
#[derive(Copy, Clone, Debug)]
pub enum Base {
A,
C,
T,
G,
N,
R,
Y,
S,
W,
K,
M,
B,
D,
H,
V,
}
impl Base {
pub(crate) fn either_or<const DEFAULT_TO_N: bool>(a: Self, b: Self) -> Self {
match (a, b) {
(Self::A, Self::A) => Self::A,
(Self::C, Self::C) => Self::C,
(Self::G, Self::G) => Self::G,
(Self::T, Self::T) => Self::T,
(Self::A, Self::G) | (Self::G, Self::A) if !DEFAULT_TO_N => Self::R,
(Self::C, Self::T) | (Self::T, Self::C) if !DEFAULT_TO_N => Self::Y,
(Self::G, Self::C) | (Self::C, Self::G) if !DEFAULT_TO_N => Self::S,
(Self::A, Self::T) | (Self::T, Self::A) if !DEFAULT_TO_N => Self::W,
(Self::G, Self::T) | (Self::T, Self::G) if !DEFAULT_TO_N => Self::K,
(Self::A, Self::C) | (Self::C, Self::A) if !DEFAULT_TO_N => Self::M,
(_, _) => Self::N,
}
}
}
impl From<char> for Base {
#[inline]
fn from(value: char) -> Self {
match value.to_ascii_uppercase() {
'A' => Self::A,
'C' => Self::C,
'T' | 'U' => Self::T,
'G' => Self::G,
_ => Self::N,
}
}
}
#[derive(Debug, Copy, Clone)]
pub struct MateResolution {
pub(crate) ordering: Ordering,
pub(crate) recommended_base: Option<Base>,
}
impl MateResolution {
pub(crate) fn new(ordering: Ordering, recommended_base: Option<Base>) -> Self {
Self {
ordering,
recommended_base,
}
}
}
#[derive(Debug, Copy, Clone, EnumString)]
#[strum(ascii_case_insensitive)]
pub enum MateResolutionStrategy {
BaseQualMapQualFirstInPair,
BaseQualMapQualIUPAC,
BaseQualMapQualN,
MapQualBaseQualFirstInPair,
MapQualBaseQualIUPAC,
MapQualBaseQualN,
IUPAC,
N,
Original,
}
impl MateResolutionStrategy {
pub(crate) fn cmp<F: ReadFilter>(
&self,
a: &(Alignment<'_>, Record),
b: &(Alignment<'_>, Record),
read_filter: &F,
) -> MateResolution {
let a_pass = read_filter.filter_read(&a.1, Some(&a.0));
let b_pass = read_filter.filter_read(&b.1, Some(&b.0));
if a_pass && !b_pass {
return MateResolution::new(Ordering::Greater, None);
} else if b_pass && !a_pass {
return MateResolution::new(Ordering::Less, None);
} else if !a_pass && !b_pass {
return MateResolution::new(Ordering::Greater, None);
}
match self {
MateResolutionStrategy::BaseQualMapQualFirstInPair => {
Self::base_qual_map_qual_first_in_pair(a, b)
}
MateResolutionStrategy::BaseQualMapQualIUPAC => Self::base_qual_map_qual_iupac(a, b),
MateResolutionStrategy::BaseQualMapQualN => Self::base_qual_map_qual_n(a, b),
MateResolutionStrategy::MapQualBaseQualFirstInPair => {
Self::map_qual_base_qual_first_in_pair(a, b)
}
MateResolutionStrategy::MapQualBaseQualIUPAC => Self::map_qual_base_qual_iupac(a, b),
MateResolutionStrategy::MapQualBaseQualN => Self::map_qual_base_qual_n(a, b),
MateResolutionStrategy::IUPAC => Self::resolve_base::<false>(a, b),
MateResolutionStrategy::N => Self::resolve_base::<true>(a, b),
MateResolutionStrategy::Original => Self::original(a, b),
}
}
pub(crate) fn resolve_base<const DEFAULT_TO_N: bool>(
a: &(Alignment<'_>, Record),
b: &(Alignment<'_>, Record),
) -> MateResolution {
let a_is_not_base = a.0.qpos().is_none();
let b_is_not_base = b.0.qpos().is_none();
if a_is_not_base || b_is_not_base {
return Self::original(a, b);
}
let a_base = Base::from(a.1.seq()[a.0.qpos().unwrap()] as char);
let b_base = Base::from(b.1.seq()[b.0.qpos().unwrap()] as char);
MateResolution::new(
Ordering::Greater,
Some(Base::either_or::<DEFAULT_TO_N>(a_base, b_base)),
)
}
pub(crate) fn base_qual_map_qual_n(
a: &(Alignment<'_>, Record),
b: &(Alignment<'_>, Record),
) -> MateResolution {
let a_is_not_base = a.0.qpos().is_none();
let b_is_not_base = b.0.qpos().is_none();
if a_is_not_base || b_is_not_base {
return Self::original(a, b);
}
let a_qual = a.1.qual()[a.0.qpos().unwrap()];
let b_qual = b.1.qual()[b.0.qpos().unwrap()];
match a_qual.cmp(&b_qual) {
Ordering::Greater => MateResolution::new(Ordering::Greater, None),
Ordering::Less => MateResolution::new(Ordering::Less, None),
Ordering::Equal => match a.1.mapq().cmp(&b.1.mapq()) {
Ordering::Greater => MateResolution::new(Ordering::Greater, None),
Ordering::Less => MateResolution::new(Ordering::Less, None),
Ordering::Equal => {
let a_base = Base::from(a.1.seq()[a.0.qpos().unwrap()] as char);
let b_base = Base::from(b.1.seq()[b.0.qpos().unwrap()] as char);
let base = Base::either_or::<true>(a_base, b_base);
MateResolution::new(Ordering::Greater, Some(base)) }
},
}
}
pub(crate) fn base_qual_map_qual_iupac(
a: &(Alignment<'_>, Record),
b: &(Alignment<'_>, Record),
) -> MateResolution {
let a_is_not_base = a.0.qpos().is_none();
let b_is_not_base = b.0.qpos().is_none();
if a_is_not_base || b_is_not_base {
return Self::original(a, b);
}
let a_qual = a.1.qual()[a.0.qpos().unwrap()];
let b_qual = b.1.qual()[b.0.qpos().unwrap()];
match a_qual.cmp(&b_qual) {
Ordering::Greater => MateResolution::new(Ordering::Greater, None),
Ordering::Less => MateResolution::new(Ordering::Less, None),
Ordering::Equal => match a.1.mapq().cmp(&b.1.mapq()) {
Ordering::Greater => MateResolution::new(Ordering::Greater, None),
Ordering::Less => MateResolution::new(Ordering::Less, None),
Ordering::Equal => {
let a_base = Base::from(a.1.seq()[a.0.qpos().unwrap()] as char);
let b_base = Base::from(b.1.seq()[b.0.qpos().unwrap()] as char);
MateResolution::new(
Ordering::Greater,
Some(Base::either_or::<false>(a_base, b_base)),
)
}
},
}
}
pub(crate) fn base_qual_map_qual_first_in_pair(
a: &(Alignment<'_>, Record),
b: &(Alignment<'_>, Record),
) -> MateResolution {
let a_is_not_base = a.0.qpos().is_none();
let b_is_not_base = b.0.qpos().is_none();
if a_is_not_base || b_is_not_base {
return Self::original(a, b);
}
let a_qual = a.1.qual()[a.0.qpos().unwrap()];
let b_qual = b.1.qual()[b.0.qpos().unwrap()];
match a_qual.cmp(&b_qual) {
Ordering::Greater => MateResolution::new(Ordering::Greater, None),
Ordering::Less => MateResolution::new(Ordering::Less, None),
Ordering::Equal => Self::original(a, b),
}
}
pub(crate) fn map_qual_base_qual_n(
a: &(Alignment<'_>, Record),
b: &(Alignment<'_>, Record),
) -> MateResolution {
let a_is_not_base = a.0.qpos().is_none();
let b_is_not_base = b.0.qpos().is_none();
if a_is_not_base || b_is_not_base {
return Self::original(a, b);
}
match a.1.mapq().cmp(&b.1.mapq()) {
Ordering::Greater => MateResolution::new(Ordering::Greater, None),
Ordering::Less => MateResolution::new(Ordering::Less, None),
Ordering::Equal => {
let a_qual = a.1.qual()[a.0.qpos().unwrap()];
let b_qual = b.1.qual()[b.0.qpos().unwrap()];
match a_qual.cmp(&b_qual) {
Ordering::Greater => MateResolution::new(Ordering::Greater, None),
Ordering::Less => MateResolution::new(Ordering::Less, None),
Ordering::Equal => {
let a_base = Base::from(a.1.seq()[a.0.qpos().unwrap()] as char);
let b_base = Base::from(b.1.seq()[b.0.qpos().unwrap()] as char);
let base = Base::either_or::<true>(a_base, b_base);
MateResolution::new(Ordering::Greater, Some(base)) }
}
}
}
}
pub(crate) fn map_qual_base_qual_iupac(
a: &(Alignment<'_>, Record),
b: &(Alignment<'_>, Record),
) -> MateResolution {
let a_is_not_base = a.0.qpos().is_none();
let b_is_not_base = b.0.qpos().is_none();
if a_is_not_base || b_is_not_base {
return Self::original(a, b);
}
match a.1.mapq().cmp(&b.1.mapq()) {
Ordering::Greater => MateResolution::new(Ordering::Greater, None),
Ordering::Less => MateResolution::new(Ordering::Less, None),
Ordering::Equal => {
let a_qual = a.1.qual()[a.0.qpos().unwrap()];
let b_qual = b.1.qual()[b.0.qpos().unwrap()];
match a_qual.cmp(&b_qual) {
Ordering::Greater => MateResolution::new(Ordering::Greater, None),
Ordering::Less => MateResolution::new(Ordering::Less, None),
Ordering::Equal => {
let a_base = Base::from(a.1.seq()[a.0.qpos().unwrap()] as char);
let b_base = Base::from(b.1.seq()[b.0.qpos().unwrap()] as char);
MateResolution::new(
Ordering::Greater,
Some(Base::either_or::<false>(a_base, b_base)),
)
}
}
}
}
}
pub(crate) fn map_qual_base_qual_first_in_pair(
a: &(Alignment<'_>, Record),
b: &(Alignment<'_>, Record),
) -> MateResolution {
let a_is_not_base = a.0.qpos().is_none();
let b_is_not_base = b.0.qpos().is_none();
if a_is_not_base || b_is_not_base {
return Self::original(a, b);
}
match a.1.mapq().cmp(&b.1.mapq()) {
Ordering::Greater => MateResolution::new(Ordering::Greater, None),
Ordering::Less => MateResolution::new(Ordering::Less, None),
Ordering::Equal => {
let a_qual = a.1.qual()[a.0.qpos().unwrap()];
let b_qual = b.1.qual()[b.0.qpos().unwrap()];
match a_qual.cmp(&b_qual) {
Ordering::Greater => MateResolution::new(Ordering::Greater, None),
Ordering::Less => MateResolution::new(Ordering::Less, None),
Ordering::Equal => {
if a.1.flags() & 64 != 0 {
MateResolution::new(Ordering::Greater, None)
} else if b.1.flags() & 64 != 0 {
MateResolution::new(Ordering::Less, None)
} else {
MateResolution::new(Ordering::Greater, None)
}
}
}
}
}
}
pub(crate) fn original(
a: &(Alignment<'_>, Record),
b: &(Alignment<'_>, Record),
) -> MateResolution {
match a.1.mapq().cmp(&b.1.mapq()) {
Ordering::Greater => MateResolution::new(Ordering::Greater, None),
Ordering::Less => MateResolution::new(Ordering::Less, None),
Ordering::Equal => {
if a.1.flags() & 64 != 0 {
MateResolution::new(Ordering::Greater, None)
} else if b.1.flags() & 64 != 0 {
MateResolution::new(Ordering::Less, None)
} else {
MateResolution::new(Ordering::Greater, None)
}
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use rust_htslib::bam::{self, record::Record};
#[test]
fn test_base_either_or_identical() {
assert!(matches!(
Base::either_or::<false>(Base::A, Base::A),
Base::A
));
assert!(matches!(
Base::either_or::<false>(Base::C, Base::C),
Base::C
));
assert!(matches!(
Base::either_or::<false>(Base::G, Base::G),
Base::G
));
assert!(matches!(
Base::either_or::<false>(Base::T, Base::T),
Base::T
));
}
#[test]
fn test_base_either_or_iupac() {
assert!(matches!(
Base::either_or::<false>(Base::A, Base::G),
Base::R
));
assert!(matches!(
Base::either_or::<false>(Base::G, Base::A),
Base::R
));
assert!(matches!(
Base::either_or::<false>(Base::C, Base::T),
Base::Y
));
assert!(matches!(
Base::either_or::<false>(Base::T, Base::C),
Base::Y
));
assert!(matches!(
Base::either_or::<false>(Base::G, Base::C),
Base::S
));
assert!(matches!(
Base::either_or::<false>(Base::C, Base::G),
Base::S
));
assert!(matches!(
Base::either_or::<false>(Base::A, Base::T),
Base::W
));
assert!(matches!(
Base::either_or::<false>(Base::T, Base::A),
Base::W
));
assert!(matches!(
Base::either_or::<false>(Base::G, Base::T),
Base::K
));
assert!(matches!(
Base::either_or::<false>(Base::T, Base::G),
Base::K
));
assert!(matches!(
Base::either_or::<false>(Base::A, Base::C),
Base::M
));
assert!(matches!(
Base::either_or::<false>(Base::C, Base::A),
Base::M
));
}
#[test]
fn test_base_either_or_default_to_n() {
assert!(matches!(Base::either_or::<true>(Base::A, Base::G), Base::N));
assert!(matches!(Base::either_or::<true>(Base::C, Base::T), Base::N));
assert!(matches!(Base::either_or::<true>(Base::G, Base::C), Base::N));
assert!(matches!(Base::either_or::<true>(Base::A, Base::A), Base::A));
assert!(matches!(Base::either_or::<true>(Base::C, Base::C), Base::C));
}
#[test]
fn test_base_from_char() {
assert!(matches!(Base::from('A'), Base::A));
assert!(matches!(Base::from('C'), Base::C));
assert!(matches!(Base::from('T'), Base::T));
assert!(matches!(Base::from('G'), Base::G));
assert!(matches!(Base::from('a'), Base::A));
assert!(matches!(Base::from('c'), Base::C));
assert!(matches!(Base::from('t'), Base::T));
assert!(matches!(Base::from('g'), Base::G));
assert!(matches!(Base::from('U'), Base::T));
assert!(matches!(Base::from('u'), Base::T));
assert!(matches!(Base::from('X'), Base::N));
assert!(matches!(Base::from('?'), Base::N));
assert!(matches!(Base::from('1'), Base::N));
}
#[test]
fn test_mate_resolution_construction() {
let res = MateResolution::new(Ordering::Greater, Some(Base::N));
assert_eq!(res.ordering, Ordering::Greater);
assert!(matches!(res.recommended_base, Some(Base::N)));
}
#[allow(clippy::too_many_arguments)]
fn test_strategy_with_bam(
strategy: MateResolutionStrategy,
read1_seq: &[u8],
read1_qual: &[u8],
read1_mapq: u8,
read1_flags: u16,
read2_seq: &[u8],
read2_qual: &[u8],
read2_mapq: u8,
read2_flags: u16,
) -> MateResolution {
use rust_htslib::bam::{HeaderView, IndexedReader, Read, Writer, index};
use tempfile::tempdir;
let tempdir = tempdir().unwrap();
let bam_path = tempdir.path().join("test.bam");
let mut header = bam::header::Header::new();
let mut chr1 = bam::header::HeaderRecord::new(b"SQ");
chr1.push_tag(b"SN", &"chr1".to_owned());
chr1.push_tag(b"LN", &"100".to_owned());
header.push_record(&chr1);
let view = HeaderView::from_header(&header);
let records = vec![
Record::from_sam(
&view,
format!(
"TESTPAIR\t{}\tchr1\t11\t{}\t10M\tchr1\t16\t30\t{}\t{}",
read1_flags,
read1_mapq,
std::str::from_utf8(read1_seq).unwrap(),
std::str::from_utf8(read1_qual).unwrap()
)
.as_bytes(),
)
.unwrap(),
Record::from_sam(
&view,
format!(
"TESTPAIR\t{}\tchr1\t16\t{}\t10M\tchr1\t11\t30\t{}\t{}",
read2_flags,
read2_mapq,
std::str::from_utf8(read2_seq).unwrap(),
std::str::from_utf8(read2_qual).unwrap()
)
.as_bytes(),
)
.unwrap(),
];
let mut writer = Writer::from_path(&bam_path, &header, bam::Format::Bam).unwrap();
for record in &records {
writer.write(record).unwrap();
}
drop(writer);
index::build(&bam_path, None, index::Type::Bai, 1).unwrap();
let mut reader = IndexedReader::from_path(&bam_path).unwrap();
reader.fetch(("chr1", 15, 20)).unwrap(); let pileup_iter = reader.pileup();
let read_filter = crate::read_filter::DefaultReadFilter::new(0, 0, 0);
for pileup_result in pileup_iter {
let pileup = pileup_result.unwrap();
if pileup.pos() >= 15 && pileup.pos() < 20 {
let alns: Vec<_> = pileup
.alignments()
.map(|aln| {
let rec = aln.record();
(aln, rec)
})
.collect();
if alns.len() == 2 {
return strategy.cmp(&alns[0], &alns[1], &read_filter);
}
}
}
panic!("Failed to find overlapping reads at test position");
}
#[test]
fn test_base_qual_map_qual_first_in_pair() {
let result = test_strategy_with_bam(
MateResolutionStrategy::BaseQualMapQualFirstInPair,
b"AAAAAAAAAA",
b"##########",
30,
67, b"CCCCCCCCCC",
b">>>>>>>>>>",
30,
147, );
assert_eq!(result.ordering, Ordering::Less); assert!(result.recommended_base.is_none());
let result = test_strategy_with_bam(
MateResolutionStrategy::BaseQualMapQualFirstInPair,
b"AAAAAAAAAA",
b">>>>>>>>>>",
40,
67, b"CCCCCCCCCC",
b">>>>>>>>>>",
30,
147, );
assert_eq!(result.ordering, Ordering::Greater); assert!(result.recommended_base.is_none());
let result = test_strategy_with_bam(
MateResolutionStrategy::BaseQualMapQualFirstInPair,
b"AAAAAAAAAA",
b">>>>>>>>>>",
30,
67, b"CCCCCCCCCC",
b">>>>>>>>>>",
30,
147, );
assert_eq!(result.ordering, Ordering::Greater); assert!(result.recommended_base.is_none());
}
#[test]
fn test_base_qual_map_qual_iupac() {
let result = test_strategy_with_bam(
MateResolutionStrategy::BaseQualMapQualIUPAC,
b"AAAAAAAAAA",
b"##########",
30,
67, b"CCCCCCCCCC",
b">>>>>>>>>>",
30,
147, );
assert_eq!(result.ordering, Ordering::Less); assert!(result.recommended_base.is_none());
let result = test_strategy_with_bam(
MateResolutionStrategy::BaseQualMapQualIUPAC,
b"AAAAAAAAAA",
b">>>>>>>>>>",
30,
67, b"GGGGGGGGGG",
b">>>>>>>>>>",
30,
147, );
assert_eq!(result.ordering, Ordering::Greater); assert!(matches!(result.recommended_base, Some(Base::R))); }
#[test]
fn test_base_qual_map_qual_n() {
let result = test_strategy_with_bam(
MateResolutionStrategy::BaseQualMapQualN,
b"AAAAAAAAAA",
b"##########",
30,
67, b"CCCCCCCCCC",
b">>>>>>>>>>",
30,
147, );
assert_eq!(result.ordering, Ordering::Less); assert!(result.recommended_base.is_none());
let result = test_strategy_with_bam(
MateResolutionStrategy::BaseQualMapQualN,
b"AAAAAAAAAA",
b">>>>>>>>>>",
30,
67, b"CCCCCCCCCC",
b">>>>>>>>>>",
30,
147, );
assert_eq!(result.ordering, Ordering::Greater); assert!(matches!(result.recommended_base, Some(Base::N))); }
#[test]
fn test_map_qual_base_qual_first_in_pair() {
let result = test_strategy_with_bam(
MateResolutionStrategy::MapQualBaseQualFirstInPair,
b"AAAAAAAAAA",
b">>>>>>>>>>",
40,
67, b"CCCCCCCCCC",
b">>>>>>>>>>",
30,
147, );
assert_eq!(result.ordering, Ordering::Greater); assert!(result.recommended_base.is_none());
let result = test_strategy_with_bam(
MateResolutionStrategy::MapQualBaseQualFirstInPair,
b"AAAAAAAAAA",
b"##########",
30,
67, b"CCCCCCCCCC",
b">>>>>>>>>>",
30,
147, );
assert_eq!(result.ordering, Ordering::Less); assert!(result.recommended_base.is_none());
let result = test_strategy_with_bam(
MateResolutionStrategy::MapQualBaseQualFirstInPair,
b"AAAAAAAAAA",
b">>>>>>>>>>",
30,
67, b"CCCCCCCCCC",
b">>>>>>>>>>",
30,
147, );
assert_eq!(result.ordering, Ordering::Greater); assert!(result.recommended_base.is_none());
}
#[test]
fn test_map_qual_base_qual_iupac() {
let result = test_strategy_with_bam(
MateResolutionStrategy::MapQualBaseQualIUPAC,
b"AAAAAAAAAA",
b">>>>>>>>>>",
40,
67, b"CCCCCCCCCC",
b">>>>>>>>>>",
30,
147, );
assert_eq!(result.ordering, Ordering::Greater); assert!(result.recommended_base.is_none());
let result = test_strategy_with_bam(
MateResolutionStrategy::MapQualBaseQualIUPAC,
b"AAAAAAAAAA",
b">>>>>>>>>>",
30,
67, b"GGGGGGGGGG",
b">>>>>>>>>>",
30,
147, );
assert_eq!(result.ordering, Ordering::Greater); assert!(matches!(result.recommended_base, Some(Base::R))); }
#[test]
fn test_map_qual_base_qual_n() {
let result = test_strategy_with_bam(
MateResolutionStrategy::MapQualBaseQualN,
b"AAAAAAAAAA",
b">>>>>>>>>>",
40,
67, b"CCCCCCCCCC",
b">>>>>>>>>>",
30,
147, );
assert_eq!(result.ordering, Ordering::Greater); assert!(result.recommended_base.is_none());
let result = test_strategy_with_bam(
MateResolutionStrategy::MapQualBaseQualN,
b"AAAAAAAAAA",
b">>>>>>>>>>",
30,
67, b"CCCCCCCCCC",
b">>>>>>>>>>",
30,
147, );
assert_eq!(result.ordering, Ordering::Greater); assert!(matches!(result.recommended_base, Some(Base::N))); }
#[test]
fn test_iupac_strategy() {
let result = test_strategy_with_bam(
MateResolutionStrategy::IUPAC,
b"AAAAAAAAAA",
b">>>>>>>>>>",
30,
67, b"GGGGGGGGGG",
b">>>>>>>>>>",
40,
147, );
assert_eq!(result.ordering, Ordering::Greater); assert!(matches!(result.recommended_base, Some(Base::R)));
let result = test_strategy_with_bam(
MateResolutionStrategy::IUPAC,
b"AAAAAAAAAA",
b">>>>>>>>>>",
30,
67, b"AAAAAAAAAA",
b">>>>>>>>>>",
40,
147, );
assert_eq!(result.ordering, Ordering::Greater); assert!(matches!(result.recommended_base, Some(Base::A))); }
#[test]
fn test_n_strategy() {
let result = test_strategy_with_bam(
MateResolutionStrategy::N,
b"AAAAAAAAAA",
b">>>>>>>>>>",
30,
67, b"CCCCCCCCCC",
b">>>>>>>>>>",
40,
147, );
assert_eq!(result.ordering, Ordering::Greater); assert!(matches!(result.recommended_base, Some(Base::N)));
let result = test_strategy_with_bam(
MateResolutionStrategy::N,
b"AAAAAAAAAA",
b">>>>>>>>>>",
30,
67, b"AAAAAAAAAA",
b">>>>>>>>>>",
40,
147, );
assert_eq!(result.ordering, Ordering::Greater); assert!(matches!(result.recommended_base, Some(Base::A))); }
#[test]
fn test_original_strategy() {
let result = test_strategy_with_bam(
MateResolutionStrategy::Original,
b"AAAAAAAAAA",
b">>>>>>>>>>",
40,
67, b"CCCCCCCCCC",
b">>>>>>>>>>",
30,
147, );
assert_eq!(result.ordering, Ordering::Greater); assert!(result.recommended_base.is_none());
let result = test_strategy_with_bam(
MateResolutionStrategy::Original,
b"AAAAAAAAAA",
b">>>>>>>>>>",
30,
67, b"CCCCCCCCCC",
b">>>>>>>>>>",
30,
147, );
assert_eq!(result.ordering, Ordering::Greater); assert!(result.recommended_base.is_none());
let result = test_strategy_with_bam(
MateResolutionStrategy::Original,
b"AAAAAAAAAA",
b">>>>>>>>>>",
30,
147, b"CCCCCCCCCC",
b">>>>>>>>>>",
30,
67, );
assert_eq!(result.ordering, Ordering::Less); assert!(result.recommended_base.is_none());
}
}