Skip to content

Commit

Permalink
example overlap, use Arc throughout
Browse files Browse the repository at this point in the history
  • Loading branch information
brentp committed Oct 13, 2023
1 parent 1c4bec7 commit ba5d460
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 31 deletions.
29 changes: 14 additions & 15 deletions src/intersection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ use std::cmp::Ordering;
use std::collections::{vec_deque::VecDeque, BinaryHeap};
use std::io;
use std::io::{Error, ErrorKind};
//use std::rc::Rc;
use std::sync::Arc as Rc;
use std::sync::Arc;

use crate::position::{Position, PositionedIterator};

Expand All @@ -23,7 +22,7 @@ pub struct IntersectionIterator<'a> {
dequeue: VecDeque<Intersection>,

// this is only kept for error checking so we can track if intervals are out of order.
previous_interval: Option<Rc<Position>>,
previous_interval: Option<Arc<Position>>,

// this tracks which iterators have been called with Some(Positioned) for a given interval
// so that calls after the first are called with None.
Expand All @@ -38,15 +37,15 @@ pub struct IntersectionIterator<'a> {
#[derive(Debug)]
pub struct Intersection {
/// the Positioned that was intersected
pub interval: Rc<Position>,
pub interval: Arc<Position>,
/// a unique identifier indicating the source of this interval.
pub id: u32,
}

/// An Intersections wraps the base interval and a vector of overlapping intervals.
#[derive(Debug)]
pub struct Intersections {
pub base_interval: Rc<Position>,
pub base_interval: Arc<Position>,
pub overlapping: Vec<Intersection>,
}

Expand Down Expand Up @@ -122,7 +121,7 @@ impl<'a> Iterator for IntersectionIterator<'a> {
// if bi is an error return the Result here
let base_interval = match bi {
Err(e) => return Some(Err(e)),
Ok(p) => Rc::new(p),
Ok(p) => Arc::new(p),
};
if let Some(chrom) = self.chromosome_order.get(base_interval.chrom()) {
if let Some(chrom_len) = chrom.length {
Expand Down Expand Up @@ -178,9 +177,9 @@ impl<'a> Iterator for IntersectionIterator<'a> {
Ordering::Less => continue,
Ordering::Greater => break,
Ordering::Equal => overlapping_positions.push(Intersection {
// NOTE: we're effectively making a copy here, but it's only incrementing the Rc and a u32...
// we could avoid by by keeping entire intersection in Rc.
interval: Rc::clone(&o.interval),
// NOTE: we're effectively making a copy here, but it's only incrementing the Arc and a u32...
// we could avoid by by keeping entire intersection in Arc.
interval: Arc::clone(&o.interval),
id: o.id,
}),
}
Expand Down Expand Up @@ -214,7 +213,7 @@ impl<'a> IntersectionIterator<'a> {
})
}

fn init_heap(&mut self, base_interval: Rc<Position>) -> io::Result<()> {
fn init_heap(&mut self, base_interval: Arc<Position>) -> io::Result<()> {
assert!(!self.heap_initialized);
for (i, iter) in self.other_iterators.iter_mut().enumerate() {
if let Some(positioned) = iter.next_position(Some(base_interval.as_ref())) {
Expand Down Expand Up @@ -242,7 +241,7 @@ impl<'a> IntersectionIterator<'a> {
}

/// drop intervals from Q that are strictly before the base interval.
fn pop_front(&mut self, base_interval: Rc<Position>) {
fn pop_front(&mut self, base_interval: Arc<Position>) {
while !self.dequeue.is_empty()
&& Ordering::Less
== cmp(
Expand All @@ -255,7 +254,7 @@ impl<'a> IntersectionIterator<'a> {
}
}

fn out_of_order(&self, interval: Rc<Position>) -> bool {
fn out_of_order(&self, interval: Arc<Position>) -> bool {
return match &self.previous_interval {
None => false, // first interval in file.
Some(previous_interval) => {
Expand All @@ -277,12 +276,12 @@ impl<'a> IntersectionIterator<'a> {
unsafe { ptr.write_bytes(0, self.called.len()) };
}

fn pull_through_heap(&mut self, base_interval: Rc<Position>) -> io::Result<()> {
fn pull_through_heap(&mut self, base_interval: Arc<Position>) -> io::Result<()> {
self.zero_called();
if !self.heap_initialized {
// we wait til first iteration here to call init heap
// because we need the base interval.
self.init_heap(Rc::clone(&base_interval))?;
self.init_heap(Arc::clone(&base_interval))?;
}
let other_iterators = self.other_iterators.as_mut_slice();

Expand Down Expand Up @@ -339,7 +338,7 @@ impl<'a> IntersectionIterator<'a> {
}

// and we must always add the position to the Q
let rc_pos = Rc::new(position);
let rc_pos = Arc::new(position);
let intersection = Intersection {
interval: rc_pos.clone(),
id: file_index as u32,
Expand Down
68 changes: 64 additions & 4 deletions src/intersections.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,75 @@ impl Default for OverlapAmount {
}

impl Intersections {
pub fn intersections<'a>(
&'a self,
pub fn intersections(
&self,
a_mode: IntersectionMode,

Check warning on line 76 in src/intersections.rs

View workflow job for this annotation

GitHub Actions / Check

unused variable: `a_mode`

Check warning on line 76 in src/intersections.rs

View workflow job for this annotation

GitHub Actions / Test Suite

unused variable: `a_mode`
b_mode: IntersectionMode,

Check warning on line 77 in src/intersections.rs

View workflow job for this annotation

GitHub Actions / Check

unused variable: `b_mode`

Check warning on line 77 in src/intersections.rs

View workflow job for this annotation

GitHub Actions / Test Suite

unused variable: `b_mode`
a_output: IntersectionOutput,

Check warning on line 78 in src/intersections.rs

View workflow job for this annotation

GitHub Actions / Check

unused variable: `a_output`

Check warning on line 78 in src/intersections.rs

View workflow job for this annotation

GitHub Actions / Test Suite

unused variable: `a_output`
b_output: IntersectionOutput,

Check warning on line 79 in src/intersections.rs

View workflow job for this annotation

GitHub Actions / Check

unused variable: `b_output`

Check warning on line 79 in src/intersections.rs

View workflow job for this annotation

GitHub Actions / Test Suite

unused variable: `b_output`
a_requirements: OverlapAmount,

Check warning on line 80 in src/intersections.rs

View workflow job for this annotation

GitHub Actions / Check

unused variable: `a_requirements`

Check warning on line 80 in src/intersections.rs

View workflow job for this annotation

GitHub Actions / Test Suite

unused variable: `a_requirements`
b_requirements: OverlapAmount,

Check warning on line 81 in src/intersections.rs

View workflow job for this annotation

GitHub Actions / Check

unused variable: `b_requirements`

Check warning on line 81 in src/intersections.rs

View workflow job for this annotation

GitHub Actions / Test Suite

unused variable: `b_requirements`
) -> Vec<SimpleInterval<'a>> {
unimplemented!("Intersections::intersections")
) -> Vec<SimpleInterval> {
// now, given the arguments that determine what is reported (output)
// and what is required (mode), we collect the intersections
let mut results = Vec::new();

Check warning on line 85 in src/intersections.rs

View workflow job for this annotation

GitHub Actions / Check

variable does not need to be mutable

Check warning on line 85 in src/intersections.rs

View workflow job for this annotation

GitHub Actions / Test Suite

variable does not need to be mutable
let base = self.base_interval.clone();
// iterate over the intersections and check the requirements
self.overlapping.iter().for_each(|o| {
// check o vs base
let bases_overlapping =

Check warning on line 90 in src/intersections.rs

View workflow job for this annotation

GitHub Actions / Check

unused variable: `bases_overlapping`

Check warning on line 90 in src/intersections.rs

View workflow job for this annotation

GitHub Actions / Test Suite

unused variable: `bases_overlapping`
o.interval.stop().min(base.stop()) - o.interval.start().max(base.start());
});
results
}
}

// write some tests
#[cfg(test)]
mod tests {
use super::*;
use std::sync::Arc;

#[test]
fn test_simple() {
// make a single Intersections
let base = SimpleInterval {
chrom: "chr1",
start: 1,
stop: 10,
};
let other = SimpleInterval {
chrom: "chr1",
start: 3,
stop: 6,
};
let p = Position::Other(Box::new(base));
let oi1 = Intersection {
interval: Arc::new(Position::Other(Box::new(other))),
id: 0,
};
let oi2 = Intersection {
interval: Arc::new(Position::Other(Box::new(SimpleInterval {
chrom: "chr1",
start: 8,
stop: 12,
}))),
id: 1,
};
let intersections = Intersections {
base_interval: Arc::new(p),
overlapping: vec![oi1, oi2],
};

intersections
.overlapping
.iter()
.map(|o| o.interval.clone())
.for_each(|i| {
let overlap = i.stop().min(intersections.base_interval.stop())
- i.start().max(intersections.base_interval.start());
println!("overlap: {:?}", overlap);
println!("i: {:?}", i);
})
}
}
16 changes: 4 additions & 12 deletions src/position.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ pub enum Position {
Vcf(Box<crate::bedder_vcf::Record>),
Interval(crate::interval::Interval),
// catch-all in case we have another interval type.
#[cfg(feature = "dyn_positioned")]
// #[cfg(feature = "dyn_positioned")]
Other(Box<dyn Positioned>),
}

Expand All @@ -74,7 +74,7 @@ impl Position {
Position::Bed(b) => b.chrom(),
Position::Vcf(v) => v.chrom(),
Position::Interval(i) => &i.chrom,
#[cfg(feature = "dyn_positioned")]
// #[cfg(feature = "dyn_positioned")]
Position::Other(o) => o.chrom(),
}
}
Expand All @@ -85,7 +85,7 @@ impl Position {
Position::Bed(b) => b.start(),
Position::Vcf(v) => v.start(),
Position::Interval(i) => i.start,
#[cfg(feature = "dyn_positioned")]
// #[cfg(feature = "dyn_positioned")]
Position::Other(o) => o.start(),
}
}
Expand All @@ -96,20 +96,12 @@ impl Position {
Position::Bed(b) => b.stop(),
Position::Vcf(v) => v.stop(),
Position::Interval(i) => i.stop,
#[cfg(feature = "dyn_positioned")]
// #[cfg(feature = "dyn_positioned")]
Position::Other(o) => o.stop(),
}
}
}

#[cfg(feature = "dyn_positioned")]
impl Valued for Box<dyn Positioned> {
#[inline]
fn value(&self, f: Field) -> result::Result<Value, FieldError> {
self.value(f)
}
}

// Delegate the boxed version of this trait object to the inner object.
impl Positioned for Box<dyn Positioned> {
fn chrom(&self) -> &str {
Expand Down

0 comments on commit ba5d460

Please sign in to comment.