lib fix: do not permit out-of-plate destinations

This commit is contained in:
Emilia Allison 2025-01-11 09:52:25 -05:00
parent 2ea2963b22
commit 619f9594cf
Signed by: emilia
GPG Key ID: 05D5D1107E5100A1
1 changed files with 65 additions and 17 deletions

View File

@ -250,24 +250,39 @@ impl TransferRegion {
// Non-replicate transfers:
match &self.dest_region {
Region::Point(Well { row: x, col: y }) => {
Box::new(move |Well { row: i, col: j }| {
if source_wells.contains(&Well { row: i, col: j }) {
Region::Point(dest_point) => {
// Breaking from form somewhat, we really should return an entirely different
// function if a point-dest can't fit the whole source.
// If the bottom-right well of the source won't fit in the dest,
// we can abort.
let source_bottom_right = match self.source_region {
Region::Point(x) => x,
Region::Rect(w1, w2) => standardize_rectangle(&w1, &w2).1,
Region::Custom(_) => unreachable!("A point destination region cannot be paired with a custom source destination?"),
};
let bottom_right_mapped = Self::point_destination_region_calc(
source_bottom_right,
source_ul,
il_source,
il_dest,
*dest_point,
);
if bottom_right_mapped.row > self.dest_plate.plate_format.rows()
|| bottom_right_mapped.col > self.dest_plate.plate_format.columns()
{
return Box::new(|_| None);
}
Box::new(move |input| {
if source_wells.contains(&input) {
// Validity here already checked by self.validate()
Some(vec![Well {
row: x + i
.checked_sub(source_ul.row)
.expect("Point cannot have been less than UL")
.checked_div(il_source.0.unsigned_abs())
.expect("Source interleave cannot be 0")
.mul(il_dest.0.unsigned_abs()),
col: y + j
.checked_sub(source_ul.col)
.expect("Point cannot have been less than UL")
.checked_div(il_source.1.unsigned_abs())
.expect("Source interleave cannot be 0")
.mul(il_dest.1.unsigned_abs()),
}])
Some(vec![Self::point_destination_region_calc(
input,
source_ul,
il_source,
il_dest,
*dest_point,
)])
} else {
None
}
@ -387,6 +402,33 @@ impl TransferRegion {
}
}
fn point_destination_region_calc(
input: Well,
source_ul: Well,
il_source: (i8, i8),
il_dest: (i8, i8),
dest_point: Well,
) -> Well {
Well {
row: dest_point.row
+ input
.row
.checked_sub(source_ul.row)
.expect("Point cannot have been less than UL")
.checked_div(il_source.0.unsigned_abs())
.expect("Source interleave cannot be 0")
.mul(il_dest.0.unsigned_abs()),
col: dest_point.col
+ input
.col
.checked_sub(source_ul.col)
.expect("Point cannot have been less than UL")
.checked_div(il_source.1.unsigned_abs())
.expect("Source interleave cannot be 0")
.mul(il_dest.1.unsigned_abs()),
}
}
pub fn validate(&self) -> Result<(), &'static str> {
// Checks if the region does anything suspect
//
@ -400,6 +442,12 @@ impl TransferRegion {
let il_dest = self.interleave_dest;
match self.source_region {
/*
* Note 04Jan2025:
* I genuinely cannot think of a reason why we should need to validate a source
* point region???
* Like, why would it *not* be in the plate?
*/
Region::Point(_) => return Ok(()), // Should make sure it's actually in the plate, leave for
// later
Region::Rect(s1, s2) => {