use crate::Strand;
use crate::base;
use crate::interbase::Coordinate;
use crate::interval::Number;
use crate::interval::r#trait;
use crate::system::Base;
use crate::system::Interbase;
pub type Interval = crate::Interval<Interbase>;
impl Interval {
pub fn contains_next_entity(&self, coordinate: Coordinate) -> Option<bool> {
let coordinate = coordinate.nudge_forward()?;
Some(self.contains_entity(&coordinate))
}
pub fn contains_prev_entity(&self, coordinate: Coordinate) -> Option<bool> {
let coordinate = coordinate.nudge_backward()?;
Some(self.contains_entity(&coordinate))
}
pub fn into_equivalent_base(self) -> crate::interval::Interval<Base> {
let (start, end) = self.into_coordinates();
let start = start.nudge_forward().unwrap();
let end = end.nudge_backward().unwrap();
crate::interval::Interval::<Base>::try_new(start, end).unwrap()
}
}
impl r#trait::Interval<Interbase> for Interval {
fn contains_entity(&self, coordinate: &base::Coordinate) -> bool {
if self.contig() != coordinate.contig() {
return false;
}
if self.strand() != coordinate.strand() {
return false;
}
match self.strand() {
Strand::Positive => {
self.start().position().get() < coordinate.position().get()
&& self.end().position().get() >= coordinate.position().get()
}
Strand::Negative => {
self.start().position().get() >= coordinate.position().get()
&& self.end().position().get() < coordinate.position().get()
}
}
}
fn count_entities(&self) -> Number {
self.start()
.position()
.distance_unchecked(self.end().position())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Coordinate;
use crate::system::Base;
fn create_coordinate(
contig: &str,
strand: &str,
position: Number,
) -> crate::Coordinate<Interbase> {
Coordinate::try_new(contig, strand, position).unwrap()
}
fn create_base_coordinate(
contig: &str,
strand: &str,
position: Number,
) -> crate::Coordinate<Base> {
Coordinate::try_new(contig, strand, position).unwrap()
}
fn create_interval(contig: &str, strand: &str, start: Number, end: Number) -> Interval {
Interval::try_new(
create_coordinate(contig, strand, start),
create_coordinate(contig, strand, end),
)
.unwrap()
}
#[test]
fn contains() {
let interval = create_interval("seq0", "+", 10, 20);
assert!(interval.contains_coordinate(interval.start()));
assert!(interval.contains_coordinate(interval.end()));
assert!(interval.contains_coordinate(&create_coordinate("seq0", "+", 15)));
assert!(!interval.contains_coordinate(&create_coordinate("seq0", "+", 9)));
assert!(!interval.contains_coordinate(&create_coordinate("seq0", "+", 21)));
assert!(!interval.contains_coordinate(&create_coordinate("seq0", "+", 1000)));
assert!(!interval.contains_coordinate(&create_coordinate("seq1", "+", 15)));
assert!(!interval.contains_coordinate(&create_coordinate("seq0", "-", 15)));
let interval = create_interval("seq0", "-", 20, 10);
assert!(interval.contains_coordinate(interval.start()));
assert!(interval.contains_coordinate(interval.end()));
assert!(interval.contains_coordinate(&create_coordinate("seq0", "-", 15)));
assert!(!interval.contains_coordinate(&create_coordinate("seq0", "-", 21)));
assert!(!interval.contains_coordinate(&create_coordinate("seq0", "-", 9)));
assert!(!interval.contains_coordinate(&create_coordinate("seq0", "-", 0)));
assert!(!interval.contains_coordinate(&create_coordinate("seq1", "-", 15)));
assert!(!interval.contains_coordinate(&create_coordinate("seq0", "+", 15)));
}
#[test]
fn contains_entity() {
let interval = create_interval("seq0", "+", 10, 20);
assert!(!interval.contains_entity(&create_base_coordinate("seq0", "+", 10)));
assert!(interval.contains_entity(&create_base_coordinate("seq0", "+", 11)));
assert!(interval.contains_entity(&create_base_coordinate("seq0", "+", 20)));
assert!(!interval.contains_entity(&create_base_coordinate("seq0", "+", 21)));
assert!(interval.contains_entity(&create_base_coordinate("seq0", "+", 15)));
assert!(!interval.contains_entity(&create_base_coordinate("seq1", "+", 15)));
assert!(!interval.contains_entity(&create_base_coordinate("seq0", "-", 15)));
let interval = create_interval("seq0", "-", 20, 10);
assert!(!interval.contains_entity(&create_base_coordinate("seq0", "-", 21)));
assert!(interval.contains_entity(&create_base_coordinate("seq0", "-", 20)));
assert!(interval.contains_entity(&create_base_coordinate("seq0", "-", 11)));
assert!(!interval.contains_entity(&create_base_coordinate("seq0", "-", 10)));
assert!(interval.contains_entity(&create_base_coordinate("seq0", "-", 15)));
assert!(!interval.contains_entity(&create_base_coordinate("seq1", "-", 15)));
assert!(!interval.contains_entity(&create_base_coordinate("seq0", "+", 15)));
}
#[test]
fn contains_next_entity() {
let interval = create_interval("seq0", "+", 10, 20);
assert!(
!interval
.contains_next_entity(create_coordinate("seq0", "+", 9))
.unwrap()
);
assert!(
interval
.contains_next_entity(create_coordinate("seq0", "+", 10))
.unwrap()
);
assert!(
interval
.contains_next_entity(create_coordinate("seq0", "+", 19))
.unwrap()
);
assert!(
!interval
.contains_next_entity(create_coordinate("seq0", "+", 20))
.unwrap()
);
assert!(
interval
.contains_next_entity(create_coordinate("seq0", "+", 15))
.unwrap()
);
assert!(
!interval
.contains_next_entity(create_coordinate("seq1", "+", 15))
.unwrap()
);
assert!(
!interval
.contains_next_entity(create_coordinate("seq0", "-", 15))
.unwrap()
);
let interval = create_interval("seq0", "-", 20, 10);
assert!(
!interval
.contains_next_entity(create_coordinate("seq0", "-", 21))
.unwrap()
);
assert!(
interval
.contains_next_entity(create_coordinate("seq0", "-", 20))
.unwrap()
);
assert!(
interval
.contains_next_entity(create_coordinate("seq0", "-", 11))
.unwrap()
);
assert!(
!interval
.contains_next_entity(create_coordinate("seq0", "-", 10))
.unwrap()
);
assert!(
interval
.contains_next_entity(create_coordinate("seq0", "-", 15))
.unwrap()
);
assert!(
!interval
.contains_next_entity(create_coordinate("seq1", "-", 15))
.unwrap()
);
assert!(
!interval
.contains_next_entity(create_coordinate("seq0", "+", 15))
.unwrap()
);
let interval = create_interval("seq0", "+", Number::MAX - 10, Number::MAX);
assert!(
interval
.contains_next_entity(create_coordinate("seq0", "+", Number::MAX))
.is_none()
);
let interval = create_interval("seq0", "-", 10, 0);
assert!(
interval
.contains_next_entity(create_coordinate("seq0", "-", 0))
.is_none()
);
}
#[test]
fn contains_prev_entity() {
let interval = create_interval("seq0", "+", 10, 20);
assert!(
!interval
.contains_prev_entity(create_coordinate("seq0", "+", 10))
.unwrap()
);
assert!(
interval
.contains_prev_entity(create_coordinate("seq0", "+", 11))
.unwrap()
);
assert!(
interval
.contains_prev_entity(create_coordinate("seq0", "+", 20))
.unwrap()
);
assert!(
!interval
.contains_prev_entity(create_coordinate("seq0", "+", 21))
.unwrap()
);
assert!(
interval
.contains_prev_entity(create_coordinate("seq0", "+", 15))
.unwrap()
);
assert!(
!interval
.contains_prev_entity(create_coordinate("seq1", "+", 15))
.unwrap()
);
assert!(
!interval
.contains_prev_entity(create_coordinate("seq0", "-", 15))
.unwrap()
);
let interval = create_interval("seq0", "-", 20, 10);
assert!(
!interval
.contains_prev_entity(create_coordinate("seq0", "-", 20))
.unwrap()
);
assert!(
interval
.contains_prev_entity(create_coordinate("seq0", "-", 19))
.unwrap()
);
assert!(
interval
.contains_prev_entity(create_coordinate("seq0", "-", 10))
.unwrap()
);
assert!(
!interval
.contains_prev_entity(create_coordinate("seq0", "-", 9))
.unwrap()
);
assert!(
interval
.contains_prev_entity(create_coordinate("seq0", "-", 15))
.unwrap()
);
assert!(
!interval
.contains_prev_entity(create_coordinate("seq1", "-", 15))
.unwrap()
);
assert!(
!interval
.contains_prev_entity(create_coordinate("seq0", "+", 15))
.unwrap()
);
let interval = create_interval("seq0", "+", 0, 10);
assert!(
interval
.contains_prev_entity(create_coordinate("seq0", "+", 0))
.is_none()
);
let interval = create_interval("seq0", "-", Number::MAX, Number::MAX - 10);
assert!(
interval
.contains_prev_entity(create_coordinate("seq0", "-", Number::MAX))
.is_none()
);
}
}