|
|
|
@ -131,10 +131,8 @@ impl TransferRegion {
|
|
|
|
|
pub fn calculate_map(&self) -> Box<dyn Fn(Well) -> Option<Vec<Well>> + '_> {
|
|
|
|
|
// By validating first, we have a stronger guarantee that
|
|
|
|
|
// this function will not panic. :)
|
|
|
|
|
// log::debug!("Validating: {:?}", self.validate());
|
|
|
|
|
if let Err(msg) = self.validate() {
|
|
|
|
|
eprintln!("{}", msg);
|
|
|
|
|
eprintln!("This transfer will be empty.");
|
|
|
|
|
log::error!("{}\nThis transfer will be empty.", msg);
|
|
|
|
|
return Box::new(|_| None);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -184,74 +182,121 @@ impl TransferRegion {
|
|
|
|
|
let Well { row: i, col: j } = w;
|
|
|
|
|
if source_wells.contains(&w) {
|
|
|
|
|
let possible_destination_wells = create_dense_rectangle(c1, c2);
|
|
|
|
|
|
|
|
|
|
// Destination upper-left, bottom-right
|
|
|
|
|
let (d_ul, d_br) = standardize_rectangle(c1, c2);
|
|
|
|
|
|
|
|
|
|
// Source upper-left, bottom-right
|
|
|
|
|
let (s_ul, s_br) =
|
|
|
|
|
standardize_rectangle(&source_corners.0, &source_corners.1);
|
|
|
|
|
|
|
|
|
|
// Get base size of source region before interleave
|
|
|
|
|
let s_dims = (
|
|
|
|
|
s_br.row.checked_sub(s_ul.row).unwrap() + 1,
|
|
|
|
|
s_br.col.checked_sub(s_ul.col).unwrap() + 1,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Get base size of destination region before interleave
|
|
|
|
|
let d_dims = (
|
|
|
|
|
d_br.row.checked_sub(d_ul.row).unwrap() + 1,
|
|
|
|
|
d_br.col.checked_sub(d_ul.col).unwrap() + 1,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Precompute unsigned_abs: this should be cheap but
|
|
|
|
|
// this is called constantly in loops, plus prettier this way
|
|
|
|
|
let il_dest_uabs = (il_dest.0.unsigned_abs(), il_dest.1.unsigned_abs());
|
|
|
|
|
let il_source_uabs = (il_source.0.unsigned_abs(), il_source.1.unsigned_abs());
|
|
|
|
|
|
|
|
|
|
// Get the actual number of source wells in each dimension
|
|
|
|
|
// after considering interleave; essentially squish the air out of the
|
|
|
|
|
// region.
|
|
|
|
|
let number_used_src_wells = (
|
|
|
|
|
// Number of used source wells
|
|
|
|
|
(s_dims.0 + il_source.0.unsigned_abs() - 1)
|
|
|
|
|
.div_euclid(il_source.0.unsigned_abs()),
|
|
|
|
|
(s_dims.1 + il_source.1.unsigned_abs() - 1)
|
|
|
|
|
.div_euclid(il_source.1.unsigned_abs()),
|
|
|
|
|
(s_dims.0 + il_source_uabs.0 - 1)
|
|
|
|
|
.div_euclid(il_source_uabs.0),
|
|
|
|
|
(s_dims.1 + il_source_uabs.1 - 1)
|
|
|
|
|
.div_euclid(il_source_uabs.1),
|
|
|
|
|
);
|
|
|
|
|
let count = (
|
|
|
|
|
// How many times can we replicate?
|
|
|
|
|
|
|
|
|
|
// How many times can we replicate in each direction?
|
|
|
|
|
// Lazy solution: just increment the number of replicates until it wouldn't
|
|
|
|
|
// fit anymore!
|
|
|
|
|
let count = {
|
|
|
|
|
let replicate_base_size = (
|
|
|
|
|
number_used_src_wells.0 * il_dest_uabs.0,
|
|
|
|
|
number_used_src_wells.1 * il_dest_uabs.1,
|
|
|
|
|
);
|
|
|
|
|
(
|
|
|
|
|
if il_dest_uabs.0 == 0 {
|
|
|
|
|
1
|
|
|
|
|
} else {
|
|
|
|
|
(1..)
|
|
|
|
|
.position(|n| {
|
|
|
|
|
n * number_used_src_wells.0 * il_dest.0.unsigned_abs()
|
|
|
|
|
- il_dest.0.unsigned_abs()
|
|
|
|
|
(n * replicate_base_size.0)
|
|
|
|
|
.saturating_sub(il_dest_uabs.0)
|
|
|
|
|
+ 1
|
|
|
|
|
> d_dims.0
|
|
|
|
|
})
|
|
|
|
|
.unwrap() as u8,
|
|
|
|
|
.unwrap() as u8
|
|
|
|
|
},
|
|
|
|
|
if il_dest_uabs.1 == 0 {
|
|
|
|
|
1
|
|
|
|
|
} else {
|
|
|
|
|
(1..)
|
|
|
|
|
.position(|n| {
|
|
|
|
|
n * number_used_src_wells.1 * il_dest.1.unsigned_abs()
|
|
|
|
|
- il_dest.1.unsigned_abs()
|
|
|
|
|
(n * replicate_base_size.1)
|
|
|
|
|
.saturating_sub(il_dest_uabs.1)
|
|
|
|
|
+ 1
|
|
|
|
|
> d_dims.1
|
|
|
|
|
})
|
|
|
|
|
.unwrap() as u8,
|
|
|
|
|
);
|
|
|
|
|
.unwrap() as u8
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
};
|
|
|
|
|
// Normalize our i,j (source coords) to a dense rectangle consisting only
|
|
|
|
|
// of points actually in the transfer.
|
|
|
|
|
let i = i
|
|
|
|
|
.saturating_sub(s_ul.row)
|
|
|
|
|
.saturating_div(il_source.0.unsigned_abs());
|
|
|
|
|
.saturating_div(il_source_uabs.0);
|
|
|
|
|
let j = j
|
|
|
|
|
.saturating_sub(s_ul.col)
|
|
|
|
|
.saturating_div(il_source.1.unsigned_abs());
|
|
|
|
|
.saturating_div(il_source_uabs.1);
|
|
|
|
|
|
|
|
|
|
// Should not matter because of validation,
|
|
|
|
|
// but a cheap way to prevent div by 0
|
|
|
|
|
let checked_il_dest = (
|
|
|
|
|
u8::max(il_dest_uabs.0, 1u8),
|
|
|
|
|
u8::max(il_dest_uabs.1, 1u8),
|
|
|
|
|
);
|
|
|
|
|
// Precompute multiplication
|
|
|
|
|
let row_modulus = number_used_src_wells.0 * checked_il_dest.0;
|
|
|
|
|
let column_modulus = number_used_src_wells.1 * checked_il_dest.1;
|
|
|
|
|
let residue_class = (
|
|
|
|
|
(il_dest_uabs.0 * i) % row_modulus,
|
|
|
|
|
(il_dest_uabs.1 * j) % column_modulus
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
Some(
|
|
|
|
|
possible_destination_wells
|
|
|
|
|
.into_iter()
|
|
|
|
|
.filter(|Well { row: x , ..}| {
|
|
|
|
|
.filter(|Well { row: x, .. }| {
|
|
|
|
|
x.checked_sub(d_ul.row).unwrap()
|
|
|
|
|
% (number_used_src_wells.0 * il_dest.0.unsigned_abs()) // Counter along x
|
|
|
|
|
== (il_dest.0.unsigned_abs() *i)
|
|
|
|
|
% (number_used_src_wells.0 * il_dest.0.unsigned_abs())
|
|
|
|
|
% row_modulus // Counter along x
|
|
|
|
|
== residue_class.0
|
|
|
|
|
})
|
|
|
|
|
.filter(|Well { col: y, .. }| {
|
|
|
|
|
y.checked_sub(d_ul.col).unwrap()
|
|
|
|
|
% (number_used_src_wells.1 * il_dest.1.unsigned_abs()) // Counter along u
|
|
|
|
|
== (il_dest.1.unsigned_abs() *j)
|
|
|
|
|
% (number_used_src_wells.1 * il_dest.1.unsigned_abs())
|
|
|
|
|
% column_modulus // Counter along u
|
|
|
|
|
== residue_class.1
|
|
|
|
|
})
|
|
|
|
|
.filter(|Well { row: x, col: y }| {
|
|
|
|
|
// How many times have we replicated? < How many are we allowed
|
|
|
|
|
// to replicate?
|
|
|
|
|
x.checked_sub(d_ul.row).unwrap().div_euclid(
|
|
|
|
|
number_used_src_wells.0 * il_dest.0.unsigned_abs(),
|
|
|
|
|
) < count.0
|
|
|
|
|
&& y.checked_sub(d_ul.col).unwrap().div_euclid(
|
|
|
|
|
number_used_src_wells.1 * il_dest.1.unsigned_abs(),
|
|
|
|
|
) < count.1
|
|
|
|
|
x.checked_sub(d_ul.row).unwrap().div_euclid(row_modulus)
|
|
|
|
|
< count.0
|
|
|
|
|
&& y.checked_sub(d_ul.col)
|
|
|
|
|
.unwrap()
|
|
|
|
|
.div_euclid(column_modulus)
|
|
|
|
|
< count.1
|
|
|
|
|
})
|
|
|
|
|
.collect(),
|
|
|
|
|
)
|
|
|
|
@ -308,11 +353,15 @@ impl TransferRegion {
|
|
|
|
|
// log::debug!("s1.1: {}, max.1: {}", s1.1, source_max.1);
|
|
|
|
|
return Err("Source region is out-of-bounds! (Too wide)");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if il_dest == (0, 0) {
|
|
|
|
|
return Err("Refusing to pool both dimensions in a rectangular transfer!\nPlease select a point in the destination plate.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Region::Custom(_) => return Ok(()),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if il_source.0 == 0 || il_dest.1 == 0 {
|
|
|
|
|
if il_source.0 == 0 || il_source.1 == 0 {
|
|
|
|
|
return Err("Source interleave cannot be zero!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -329,7 +378,8 @@ fn create_dense_rectangle(c1: &Well, c2: &Well) -> Vec<Well> {
|
|
|
|
|
// Creates a vector of every point between two corners
|
|
|
|
|
let (c1, c2) = standardize_rectangle(c1, c2);
|
|
|
|
|
|
|
|
|
|
let mut points = Vec::<Well>::new();
|
|
|
|
|
let number_wells: usize = ((c2.row - c1.row + 1) as usize) * ((c2.col - c1.col + 1) as usize);
|
|
|
|
|
let mut points = Vec::<Well>::with_capacity(number_wells);
|
|
|
|
|
for i in c1.row..=c2.row {
|
|
|
|
|
for j in c1.col..=c2.col {
|
|
|
|
|
points.push(Well { row: i, col: j });
|
|
|
|
@ -409,85 +459,85 @@ mod tests {
|
|
|
|
|
|
|
|
|
|
let transfer1 = TransferRegion {
|
|
|
|
|
source_plate: source,
|
|
|
|
|
source_region: Region::Rect(Well{ row: 1, col: 1}, Well { row: 1, col: 1 }),
|
|
|
|
|
source_region: Region::Rect(Well { row: 1, col: 1 }, Well { row: 1, col: 1 }),
|
|
|
|
|
dest_plate: destination,
|
|
|
|
|
dest_region: Region::Point(Well {row: 3, col: 3}),
|
|
|
|
|
dest_region: Region::Point(Well { row: 3, col: 3 }),
|
|
|
|
|
interleave_source: (1, 1),
|
|
|
|
|
interleave_dest: (1, 1),
|
|
|
|
|
};
|
|
|
|
|
let transfer1_map = transfer1.calculate_map();
|
|
|
|
|
assert_eq!(
|
|
|
|
|
transfer1_map(Well {row: 1, col: 1}),
|
|
|
|
|
transfer1_map(Well { row: 1, col: 1 }),
|
|
|
|
|
Some(vec! {Well {row: 3, col: 3}}),
|
|
|
|
|
"Failed basic shift transfer 1"
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
transfer1_map(Well{ row: 1, col: 2}),
|
|
|
|
|
transfer1_map(Well { row: 1, col: 2 }),
|
|
|
|
|
Some(vec! {Well{ row: 3, col: 4}}),
|
|
|
|
|
"Failed basic shift transfer 2"
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
transfer1_map(Well{ row: 2, col: 2}),
|
|
|
|
|
transfer1_map(Well { row: 2, col: 2 }),
|
|
|
|
|
Some(vec! {Well{ row: 4, col: 4}}),
|
|
|
|
|
"Failed basic shift transfer 3"
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
let transfer2 = TransferRegion {
|
|
|
|
|
source_plate: source,
|
|
|
|
|
source_region: Region::Rect(Well{ row: 1, col: 1}, Well{ row: 3, col: 3}),
|
|
|
|
|
source_region: Region::Rect(Well { row: 1, col: 1 }, Well { row: 3, col: 3 }),
|
|
|
|
|
dest_plate: destination,
|
|
|
|
|
dest_region: Region::Point(Well{ row: 3, col: 3}),
|
|
|
|
|
dest_region: Region::Point(Well { row: 3, col: 3 }),
|
|
|
|
|
interleave_source: (2, 2),
|
|
|
|
|
interleave_dest: (1, 1),
|
|
|
|
|
};
|
|
|
|
|
let transfer2_map = transfer2.calculate_map();
|
|
|
|
|
assert_eq!(
|
|
|
|
|
transfer2_map(Well{ row: 1, col: 1}),
|
|
|
|
|
transfer2_map(Well { row: 1, col: 1 }),
|
|
|
|
|
Some(vec! {Well{ row: 3, col: 3}}),
|
|
|
|
|
"Failed source interleave, type simple 1"
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
transfer2_map(Well{ row: 1, col: 2}),
|
|
|
|
|
transfer2_map(Well { row: 1, col: 2 }),
|
|
|
|
|
None,
|
|
|
|
|
"Failed source interleave, type simple 2"
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
transfer2_map(Well{ row: 2, col: 2}),
|
|
|
|
|
transfer2_map(Well { row: 2, col: 2 }),
|
|
|
|
|
None,
|
|
|
|
|
"Failed source interleave, type simple 3"
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
transfer2_map(Well{ row: 3, col: 3}),
|
|
|
|
|
transfer2_map(Well { row: 3, col: 3 }),
|
|
|
|
|
Some(vec! {Well{ row: 4, col: 4}}),
|
|
|
|
|
"Failed source interleave, type simple 4"
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
let transfer3 = TransferRegion {
|
|
|
|
|
source_plate: source,
|
|
|
|
|
source_region: Region::Rect(Well{ row: 1, col: 1}, Well{ row: 3, col: 3}),
|
|
|
|
|
source_region: Region::Rect(Well { row: 1, col: 1 }, Well { row: 3, col: 3 }),
|
|
|
|
|
dest_plate: destination,
|
|
|
|
|
dest_region: Region::Point(Well{ row: 3, col: 3}),
|
|
|
|
|
dest_region: Region::Point(Well { row: 3, col: 3 }),
|
|
|
|
|
interleave_source: (1, 1),
|
|
|
|
|
interleave_dest: (2, 3),
|
|
|
|
|
};
|
|
|
|
|
let transfer3_map = transfer3.calculate_map();
|
|
|
|
|
assert_eq!(
|
|
|
|
|
transfer3_map(Well{ row: 1, col: 1}),
|
|
|
|
|
transfer3_map(Well { row: 1, col: 1 }),
|
|
|
|
|
Some(vec! {Well{ row: 3, col: 3}}),
|
|
|
|
|
"Failed destination interleave, type simple 1"
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
transfer3_map(Well{ row: 2, col: 1}),
|
|
|
|
|
transfer3_map(Well { row: 2, col: 1 }),
|
|
|
|
|
Some(vec! {Well{ row: 5, col: 3}}),
|
|
|
|
|
"Failed destination interleave, type simple 2"
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
transfer3_map(Well{ row: 1, col: 2}),
|
|
|
|
|
transfer3_map(Well { row: 1, col: 2 }),
|
|
|
|
|
Some(vec! {Well{ row: 3, col: 6}}),
|
|
|
|
|
"Failed destination interleave, type simple 3"
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
transfer3_map(Well{ row: 2, col: 2}),
|
|
|
|
|
transfer3_map(Well { row: 2, col: 2 }),
|
|
|
|
|
Some(vec! {Well{ row: 5, col: 6}}),
|
|
|
|
|
"Failed destination interleave, type simple 4"
|
|
|
|
|
);
|
|
|
|
@ -500,29 +550,33 @@ mod tests {
|
|
|
|
|
|
|
|
|
|
let transfer1 = TransferRegion {
|
|
|
|
|
source_plate: source,
|
|
|
|
|
source_region: Region::Rect(Well{ row: 1, col: 1}, Well{ row: 2, col: 2}),
|
|
|
|
|
source_region: Region::Rect(Well { row: 1, col: 1 }, Well { row: 2, col: 2 }),
|
|
|
|
|
dest_plate: destination,
|
|
|
|
|
dest_region: Region::Rect(Well{ row: 2, col: 2}, Well{row:11, col:11}),
|
|
|
|
|
dest_region: Region::Rect(Well { row: 2, col: 2 }, Well { row: 11, col: 11 }),
|
|
|
|
|
interleave_source: (1, 1),
|
|
|
|
|
interleave_dest: (3, 3),
|
|
|
|
|
};
|
|
|
|
|
let transfer1_map = transfer1.calculate_map();
|
|
|
|
|
assert_eq!(
|
|
|
|
|
transfer1_map(Well{ row: 1, col: 1}),
|
|
|
|
|
Some(vec! {Well{ row: 2, col: 2}, Well{ row: 2, col: 8}, Well{ row: 8, col: 2}, Well{ row: 8, col: 8}}),
|
|
|
|
|
transfer1_map(Well { row: 1, col: 1 }),
|
|
|
|
|
Some(
|
|
|
|
|
vec! {Well{ row: 2, col: 2}, Well{ row: 2, col: 8}, Well{ row: 8, col: 2}, Well{ row: 8, col: 8}}
|
|
|
|
|
),
|
|
|
|
|
"Failed type replicate 1"
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
transfer1_map(Well{ row: 2, col: 1}),
|
|
|
|
|
Some(vec! {Well{ row: 5, col: 2}, Well{ row: 5, col: 8}, Well{ row: 11, col: 2}, Well{ row: 11, col: 8}}),
|
|
|
|
|
transfer1_map(Well { row: 2, col: 1 }),
|
|
|
|
|
Some(
|
|
|
|
|
vec! {Well{ row: 5, col: 2}, Well{ row: 5, col: 8}, Well{ row: 11, col: 2}, Well{ row: 11, col: 8}}
|
|
|
|
|
),
|
|
|
|
|
"Failed type replicate 1"
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
let transfer2 = TransferRegion {
|
|
|
|
|
source_plate: Plate::new(PlateType::Source, PlateFormat::W384),
|
|
|
|
|
dest_plate: Plate::new(PlateType::Destination, PlateFormat::W384),
|
|
|
|
|
source_region: Region::Rect(Well{ row: 1, col: 1}, Well{ row: 2, col: 3}),
|
|
|
|
|
dest_region: Region::Rect(Well{ row: 2, col: 2}, Well{ row: 11, col: 16}),
|
|
|
|
|
source_region: Region::Rect(Well { row: 1, col: 1 }, Well { row: 2, col: 3 }),
|
|
|
|
|
dest_region: Region::Rect(Well { row: 2, col: 2 }, Well { row: 11, col: 16 }),
|
|
|
|
|
interleave_source: (1, 1),
|
|
|
|
|
interleave_dest: (2, 2),
|
|
|
|
|
};
|
|
|
|
@ -530,36 +584,43 @@ mod tests {
|
|
|
|
|
let transfer2_dest = transfer2.get_destination_wells();
|
|
|
|
|
assert_eq!(
|
|
|
|
|
transfer2_source,
|
|
|
|
|
vec![Well{ row: 1, col: 1}, Well{ row: 1, col: 2}, Well{ row: 1, col: 3}, Well{ row: 2, col: 1}, Well{ row: 2, col: 2}, Well{ row: 2, col: 3}],
|
|
|
|
|
vec![
|
|
|
|
|
Well { row: 1, col: 1 },
|
|
|
|
|
Well { row: 1, col: 2 },
|
|
|
|
|
Well { row: 1, col: 3 },
|
|
|
|
|
Well { row: 2, col: 1 },
|
|
|
|
|
Well { row: 2, col: 2 },
|
|
|
|
|
Well { row: 2, col: 3 }
|
|
|
|
|
],
|
|
|
|
|
"Failed type replicate 2 source"
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
transfer2_dest,
|
|
|
|
|
vec![
|
|
|
|
|
Well{ row: 2, col: 2},
|
|
|
|
|
Well{ row: 2, col: 8},
|
|
|
|
|
Well{ row: 6, col: 2},
|
|
|
|
|
Well{ row: 6, col: 8},
|
|
|
|
|
Well{ row: 2, col: 4},
|
|
|
|
|
Well{ row: 2, col: 10},
|
|
|
|
|
Well{ row: 6, col: 4},
|
|
|
|
|
Well{ row: 6, col: 10},
|
|
|
|
|
Well{ row: 2, col: 6},
|
|
|
|
|
Well{ row: 2, col: 12},
|
|
|
|
|
Well{ row: 6, col: 6},
|
|
|
|
|
Well{ row: 6, col: 12},
|
|
|
|
|
Well{ row: 4, col: 2},
|
|
|
|
|
Well{ row: 4, col: 8},
|
|
|
|
|
Well{ row: 8, col: 2},
|
|
|
|
|
Well{ row: 8, col: 8},
|
|
|
|
|
Well{ row: 4, col: 4},
|
|
|
|
|
Well{ row: 4, col: 10},
|
|
|
|
|
Well{ row: 8, col: 4},
|
|
|
|
|
Well{ row: 8, col: 10},
|
|
|
|
|
Well{ row: 4, col: 6},
|
|
|
|
|
Well{ row: 4, col: 12},
|
|
|
|
|
Well{ row: 8, col: 6},
|
|
|
|
|
Well{ row: 8, col: 12}
|
|
|
|
|
Well { row: 2, col: 2 },
|
|
|
|
|
Well { row: 2, col: 8 },
|
|
|
|
|
Well { row: 6, col: 2 },
|
|
|
|
|
Well { row: 6, col: 8 },
|
|
|
|
|
Well { row: 2, col: 4 },
|
|
|
|
|
Well { row: 2, col: 10 },
|
|
|
|
|
Well { row: 6, col: 4 },
|
|
|
|
|
Well { row: 6, col: 10 },
|
|
|
|
|
Well { row: 2, col: 6 },
|
|
|
|
|
Well { row: 2, col: 12 },
|
|
|
|
|
Well { row: 6, col: 6 },
|
|
|
|
|
Well { row: 6, col: 12 },
|
|
|
|
|
Well { row: 4, col: 2 },
|
|
|
|
|
Well { row: 4, col: 8 },
|
|
|
|
|
Well { row: 8, col: 2 },
|
|
|
|
|
Well { row: 8, col: 8 },
|
|
|
|
|
Well { row: 4, col: 4 },
|
|
|
|
|
Well { row: 4, col: 10 },
|
|
|
|
|
Well { row: 8, col: 4 },
|
|
|
|
|
Well { row: 8, col: 10 },
|
|
|
|
|
Well { row: 4, col: 6 },
|
|
|
|
|
Well { row: 4, col: 12 },
|
|
|
|
|
Well { row: 8, col: 6 },
|
|
|
|
|
Well { row: 8, col: 12 }
|
|
|
|
|
],
|
|
|
|
|
"Failed type replicate 2 destination"
|
|
|
|
|
);
|
|
|
|
@ -571,8 +632,8 @@ mod tests {
|
|
|
|
|
let transfer1 = TransferRegion {
|
|
|
|
|
source_plate: Plate::new(PlateType::Source, PlateFormat::W384),
|
|
|
|
|
dest_plate: Plate::new(PlateType::Destination, PlateFormat::W384),
|
|
|
|
|
source_region: Region::Rect(Well{ row: 1, col: 4}, Well{ row: 3, col: 7}),
|
|
|
|
|
dest_region: Region::Point(Well{ row: 1, col: 9}),
|
|
|
|
|
source_region: Region::Rect(Well { row: 1, col: 4 }, Well { row: 3, col: 7 }),
|
|
|
|
|
dest_region: Region::Point(Well { row: 1, col: 9 }),
|
|
|
|
|
interleave_source: (1, 1),
|
|
|
|
|
interleave_dest: (0, 2),
|
|
|
|
|
};
|
|
|
|
@ -582,17 +643,24 @@ mod tests {
|
|
|
|
|
// Skipping source check---it's just 12 wells.
|
|
|
|
|
assert_eq!(
|
|
|
|
|
transfer1_dest,
|
|
|
|
|
vec![Well{ row: 1, col: 9}, Well{ row: 1, col: 11}, Well{ row: 1, col: 13}, Well{ row: 1, col: 15}].into_iter().collect(),
|
|
|
|
|
vec![
|
|
|
|
|
Well { row: 1, col: 9 },
|
|
|
|
|
Well { row: 1, col: 11 },
|
|
|
|
|
Well { row: 1, col: 13 },
|
|
|
|
|
Well { row: 1, col: 15 }
|
|
|
|
|
]
|
|
|
|
|
.into_iter()
|
|
|
|
|
.collect(),
|
|
|
|
|
"Failed type pool 1 dest"
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
transfer1_map(Well{ row: 2, col: 6}),
|
|
|
|
|
Some(vec![Well{ row: 1, col: 13}]),
|
|
|
|
|
transfer1_map(Well { row: 2, col: 6 }),
|
|
|
|
|
Some(vec![Well { row: 1, col: 13 }]),
|
|
|
|
|
"Failed type pool 1 map 1"
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
transfer1_map(Well{ row: 3, col: 7}),
|
|
|
|
|
Some(vec![Well{ row: 1, col: 15}]),
|
|
|
|
|
transfer1_map(Well { row: 3, col: 7 }),
|
|
|
|
|
Some(vec![Well { row: 1, col: 15 }]),
|
|
|
|
|
"Failed type pool 1 map 2"
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|