use coitrees::{BasicCOITree, GenericInterval, Interval, IntervalNode, IntervalTree};
use crate::{
error::GRangesError,
traits::IterableRangeContainer,
traits::{GenericRange, RangeContainer},
Position,
};
use super::{validate_range, vec::VecRanges, RangeEmpty, RangeIndexed};
pub type COITreesIndexed = COITrees<usize>;
pub type COITreesEmpty = COITrees<()>;
pub struct COITrees<M: Clone> {
pub(crate) ranges: BasicCOITree<M, usize>,
pub length: Position,
}
impl<M: Clone> std::fmt::Debug for COITrees<M> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("COITrees")
.field("number of ranges:", &self.ranges.len())
.field("length", &self.length)
.finish_non_exhaustive()
}
}
impl<M: Clone> COITrees<M> {
pub fn validate_range(&self, start: Position, end: Position) -> Result<(), GRangesError> {
validate_range(start, end, self.length)
}
pub fn query<F>(&self, start: Position, end: Position, visit: F)
where
F: FnMut(&IntervalNode<M, usize>),
{
let first = start.try_into().expect("could not covert");
let end: i32 = end.try_into().expect("could not covert");
self.ranges.query(first, end - 1, visit)
}
pub fn count_overlaps(&self, start: Position, end: Position) -> usize {
let first = start.try_into().expect("could not covert");
let end: i32 = end.try_into().expect("could not covert");
self.ranges.query_count(first, end - 1)
}
pub fn len(&self) -> usize {
self.ranges.len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl<R: Clone + GenericInterval<M>, M: Clone> From<VecRanges<R>> for COITrees<M> {
fn from(value: VecRanges<R>) -> Self {
let ranges = BasicCOITree::new(&value.ranges);
let length = value.length;
Self { ranges, length }
}
}
impl From<COITrees<usize>> for VecRanges<RangeIndexed> {
fn from(value: COITrees<usize>) -> Self {
let length = value.length;
let mut ranges: VecRanges<RangeIndexed> = VecRanges::new(length);
for interval in value.ranges.iter() {
ranges.push_range(interval.into());
}
ranges
}
}
impl From<COITrees<()>> for VecRanges<RangeEmpty> {
fn from(value: COITrees<()>) -> Self {
let length = value.length;
let mut ranges: VecRanges<RangeEmpty> = VecRanges::new(length);
for interval in value.ranges.iter() {
ranges.push_range(interval.into());
}
ranges
}
}
impl<M: Clone> RangeContainer for COITrees<M> {
type InternalRangeType = IntervalNode<M, usize>;
fn len(&self) -> usize {
self.ranges.len()
}
fn sequence_length(&self) -> Position {
self.length
}
}
impl From<Interval<&()>> for RangeEmpty {
fn from(value: Interval<&()>) -> Self {
let first: Position = value.first.try_into().unwrap();
let last: Position = value.last.try_into().unwrap();
RangeEmpty {
start: first,
end: last + 1,
}
}
}
impl From<Interval<&usize>> for RangeIndexed {
fn from(value: Interval<&usize>) -> Self {
let first: Position = value.first.try_into().unwrap();
let last: Position = value.last.try_into().unwrap();
RangeIndexed {
start: first,
end: last + 1,
index: *value.metadata(),
}
}
}
impl IterableRangeContainer for COITrees<usize> {
type RangeType = RangeIndexed;
fn iter_ranges(&self) -> Box<dyn Iterator<Item = RangeIndexed> + '_> {
let iter = self.ranges.iter();
let converted_iter = iter.map(RangeIndexed::from);
Box::new(converted_iter)
}
}
impl IterableRangeContainer for COITrees<()> {
type RangeType = RangeEmpty;
fn iter_ranges(&self) -> Box<dyn Iterator<Item = RangeEmpty> + '_> {
let iter = self.ranges.iter();
let converted_iter = iter.map(RangeEmpty::from);
Box::new(converted_iter)
}
}
impl GenericInterval<()> for RangeEmpty {
fn first(&self) -> i32 {
self.start.try_into().unwrap()
}
fn last(&self) -> i32 {
let end: i32 = self.end.try_into().unwrap();
end - 1
}
fn metadata(&self) -> &() {
&()
}
}
impl GenericInterval<usize> for RangeIndexed {
fn first(&self) -> i32 {
self.start.try_into().unwrap()
}
fn last(&self) -> i32 {
let end: i32 = self.end.try_into().unwrap();
end - 1
}
fn metadata(&self) -> &usize {
&self.index
}
}
impl GenericRange for IntervalNode<(), usize> {
fn start(&self) -> Position {
self.first().try_into().unwrap()
}
fn end(&self) -> Position {
(self.last() + 1).try_into().unwrap()
}
fn index(&self) -> Option<usize> {
None
}
}
impl GenericRange for IntervalNode<usize, usize> {
fn start(&self) -> Position {
self.first().try_into().unwrap()
}
fn end(&self) -> Position {
(self.last() + 1).try_into().unwrap()
}
fn index(&self) -> Option<usize> {
Some(*self.metadata())
}
}
impl<M: Clone + PartialEq> PartialEq for COITrees<M> {
fn eq(&self, other: &Self) -> bool {
if self.ranges.len() != other.ranges.len() {
return false;
}
let self_ranges = self.ranges.iter();
let other_ranges = other.ranges.iter();
self_ranges.zip(other_ranges).all(|(r1, r2)| {
(r1.first == r2.first) && (r1.last == r2.last) && (r1.metadata == r2.metadata)
})
}
}
#[cfg(test)]
mod tests {
use coitrees::{GenericInterval, Interval};
use crate::prelude::*;
use crate::ranges::{RangeEmpty, RangeIndexed};
use crate::test_utilities::granges_test_case_01;
#[test]
fn test_ranges_iterable_coitrees() {
let gr = granges_test_case_01().into_coitrees().unwrap();
let mut chr1_iter = gr.get_ranges("chr1").unwrap().iter_ranges();
assert_eq!(chr1_iter.next().unwrap(), RangeIndexed::new(0, 5, 0));
assert_eq!(chr1_iter.next().unwrap(), RangeIndexed::new(4, 7, 1));
assert_eq!(chr1_iter.next().unwrap(), RangeIndexed::new(10, 17, 2));
assert!(chr1_iter.next().is_none());
}
#[test]
fn test_from_interval_to_range_empty() {
let interval: Interval<&()> = Interval::new(0, 10, &());
let range_empty: RangeEmpty = interval.into();
assert_eq!(range_empty.start, 0);
assert_eq!(range_empty.end, 11);
assert_eq!(range_empty.start(), 0);
assert_eq!(range_empty.end(), 11);
}
#[test]
fn test_from_interval_to_range_indexed() {
let interval: Interval<&usize> = Interval::new(0, 10, &0);
let range_empty: RangeIndexed = interval.into();
assert_eq!(range_empty.start, 0);
assert_eq!(range_empty.end, 11);
assert_eq!(range_empty.start(), 0);
assert_eq!(range_empty.end(), 11);
}
#[test]
fn test_generic_interval_for_range_empty() {
let range = RangeEmpty::new(0, 10);
assert_eq!(range.first(), 0);
assert_eq!(range.last(), 9);
}
#[test]
fn test_generic_interval_for_range_indexed() {
let range = RangeIndexed::new(0, 10, 1);
assert_eq!(range.first(), 0);
assert_eq!(range.last(), 9);
}
}