diff --git a/src/data/transfer_region.rs b/src/data/transfer_region.rs index 78ae68f..1f21b5e 100644 --- a/src/data/transfer_region.rs +++ b/src/data/transfer_region.rs @@ -10,10 +10,34 @@ pub struct TransferRegion<'a> { pub source_region: Region, // Even if it is just a point, we don't want corners. pub dest_plate: &'a Plate, pub dest_region: Region, - pub offset: Option<(i8,i8)>, + pub interleave_source: Option<(i8,i8)>, + pub interleave_dest: Option<(i8,i8)>, } impl TransferRegion<'_> { + pub fn get_source_wells(&self) -> Vec<(u8,u8)> { + if let Region::Rect(c1, c2) = self.source_region { + let mut wells = Vec::<(u8,u8)>::new(); + let (ul, br) = standardize_rectangle(&c1, &c2); + let (interleave_i, interleave_j) = self.interleave_source.unwrap_or((1,1)); + // NOTE: This will panic if either is 0! + // We'll reassign these values (still not mutable) just in case. + // This behaviour shouldn't be replicated for destination wells + // because a zero step permits pooling. + let (interleave_i, interleave_j) = (i8::max(interleave_i, 1), i8::max(interleave_j, 1)); + + for i in (ul.0..=br.0).step_by(i8::abs(interleave_i) as usize) { + for j in (ul.0..=br.0).step_by(i8::abs(interleave_j) as usize) { + // NOTE: It looks like we're ignoring negative interleaves, + // because it wouldn't make a difference here---the same + // wells will still be involved in the transfer. + wells.push((i,j)) + } + } + return wells; + } else { panic!("Source region is just a point!") } + } + pub fn validate(&self) -> Result<(), String> { // Checks if the region does anything suspect // @@ -87,6 +111,14 @@ fn in_region(pt: (u8,u8), r: &Region) -> bool { } } +fn standardize_rectangle(c1: &(u8,u8), c2: &(u8,u8)) -> ((u8,u8),(u8,u8)) { + let upper_left_i = u8::min(c1.0, c2.0); + let upper_left_j = u8::min(c1.1, c2.1); + let bottom_right_i = u8::max(c1.0, c2.0); + let bottom_right_j = u8::max(c1.1, c2.1); + return ((upper_left_i,upper_left_j),(bottom_right_i,bottom_right_j)); +} + #[cfg(debug_assertions)] use std::fmt; @@ -95,10 +127,11 @@ impl fmt::Display for TransferRegion<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { writeln!(f, "Source Plate:")?; let source_dims = self.source_plate.size(); + let source_wells = self.get_source_wells(); let mut source_string = String::new(); for i in 1..=source_dims.0 { for j in 1..=source_dims.1 { - if in_region((i,j), &self.source_region) { + if source_wells.contains(&(i,j)) { source_string.push_str("x") } else { source_string.push_str("o") diff --git a/src/lib.rs b/src/lib.rs index c976d85..ec4adf7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,7 +29,9 @@ pub fn plate_test() { source_region: transfer_region::Region::Rect((1,1), (6,6)), dest_plate: &destination, dest_region: transfer_region::Region::Rect((1,1), (6,6)), - offset: None + interleave_source: Some((2,1)), + interleave_dest: None }; - println!("{}", transfer) + println!("{}", transfer); + println!("{:?}", transfer.get_source_wells()); }