From ed8a11e8c78abdc1d7004757d28662d612f6274c Mon Sep 17 00:00:00 2001 From: Emilia Date: Fri, 12 May 2023 16:38:14 -0400 Subject: [PATCH] Structs for transfers, lots of fixing --- src/data/mod.rs | 2 +- src/data/plate.rs | 1 - src/data/transfer_region.rs | 138 +++++++++++++++++++++++------------- src/lib.rs | 17 +++++ src/main.rs | 6 +- 5 files changed, 112 insertions(+), 52 deletions(-) diff --git a/src/data/mod.rs b/src/data/mod.rs index c7d5e5a..e065044 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -1,2 +1,2 @@ pub mod plate; -pub mod region; +pub mod transfer_region; diff --git a/src/data/plate.rs b/src/data/plate.rs index f34a8e9..3b2203d 100644 --- a/src/data/plate.rs +++ b/src/data/plate.rs @@ -5,7 +5,6 @@ pub struct Plate { impl Plate { pub fn new(plate_type: PlateType, plate_format: PlateFormat) -> Self { - let (l,w) = plate_format.size(); Plate { plate_type, plate_format, diff --git a/src/data/transfer_region.rs b/src/data/transfer_region.rs index b8e93f2..78ae68f 100644 --- a/src/data/transfer_region.rs +++ b/src/data/transfer_region.rs @@ -1,69 +1,111 @@ use super::plate::Plate; -enum Region { +pub enum Region { Rect((u8,u8),(u8,u8)), Point(u8,u8) } -struct TransferRegion { - source_plate: &Plate, - source_region: Region::Rect, // Even if it is just a point, we don't want corners. - dest_plate: &Plate, - dest_region: Region, - offset: Option<(u8,u8)>, +pub struct TransferRegion<'a> { + pub source_plate: &'a Plate, + 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)>, } -impl TransferRegion { +impl TransferRegion<'_> { pub fn validate(&self) -> Result<(), String> { - /// Checks if the region does anything suspect - /// - /// If validation fails, we pass a string to show to the user. - /// - /// We check: - /// - Are the wells in the source really there? - /// - Are the wells in the destination there? (Sometimes running OOB is okay though?) - /// - In a replication region, do the source lengths divide the destination lengths? + // Checks if the region does anything suspect + // + // If validation fails, we pass a string to show to the user. + // + // We check: + // - Are the wells in the source really there? + // - Are the wells in the destination there? (Sometimes running OOB is okay though?) + // - In a replication region, do the source lengths divide the destination lengths? // Easy checks: - if self.source_region.0.0 == 0 || self.source_region.0.1 == 0 - || self.source_region.1.0 == 0 || self.source_region.1.1 == 0 { - Err("Source region is out-of-bounds! (Too small)") - } - - // Check if all source wells exist: - // Sufficient to check if the corners are in-bounds - let source_max = self.source_plate.size(); - if self.source_region.0.0 > source_max.0 || - self.source_region.1.0 > source_max.0 { - Err("Source region is out-of-bounds! (Too tall)") - } - if self.source_region.0.1 > source_max.1 || - self.source_region.1.1 > source_max.1 { - Err("Source region is out-of-bounds! (Too wide)") - } - - // Check if all destination wells exist: - // NOT IMPLEMENTED - - // Check that source lengths divide destination lengths - match self.dest_region { - Point => (), + match self.source_region { + Region::Point(_, _) => return Err("Source region should not be a point!".to_string()), Region::Rect(c1, c2) => { - let dest_diff_i = u8::abs_diff(c1.0, c2.0); - let dest_diff_j = u8::abs_diff(c1.1, c2.1); + // Check if all source wells exist: + if c1.0 == 0 || c1.1 == 0 + || c2.0 == 0 || c2.1 == 0 { + return Err("Source region is out-of-bounds! (Too small)".to_string()) + } + // Sufficient to check if the corners are in-bounds + let source_max = self.source_plate.size(); + if c1.0 > source_max.0 || + c2.0 > source_max.0 { + return Err("Source region is out-of-bounds! (Too tall)".to_string()) + } + if c1.1 > source_max.1 || + c2.1 > source_max.1 { + return Err("Source region is out-of-bounds! (Too wide)".to_string()) + } + // Check that source lengths divide destination lengths + match &self.dest_region { + Region::Point(_,_) => (), + Region::Rect(c1, c2) => { + let dest_diff_i = u8::abs_diff(c1.0, c2.0); + let dest_diff_j = u8::abs_diff(c1.1, c2.1); - let source_diff_i = u8::abs_diff(self.source_region.0.0, self.source_region.1.0); - let source_diff_j = u8::abs_diff(self.source_region.0.1, self.source_region.1.1); + let source_diff_i = u8::abs_diff(c1.0, c2.0); + let source_diff_j = u8::abs_diff(c1.1, c2.1); - if source_diff_i % dest_diff_i != 0 { - Err("Replicate region has indivisible height!") - } - if source_diff_j % dest_diff_j != 0 { - Err("Replicate region has indivisible width!") + if source_diff_i % dest_diff_i != 0 { + return Err("Replicate region has indivisible height!".to_string()) + } + if source_diff_j % dest_diff_j != 0 { + return Err("Replicate region has indivisible width!".to_string()) + } + } } } } + + // Check if all destination wells exist: + // NOT IMPLEMENTED + + return Ok(()) } } + +fn in_region(pt: (u8,u8), r: &Region) -> bool { + match r { + Region::Rect(c1, c2) => { + pt.0 <= u8::max(c1.0, c2.0) + && pt.0 >= u8::min(c1.0, c2.0) + && pt.1 <= u8::max(c1.1, c2.1) + && pt.1 >= u8::min(c1.1, c2.1) + }, + Region::Point(i, j) => { + pt.0 == *i && pt.1 == *j + } + } +} + +#[cfg(debug_assertions)] +use std::fmt; + +#[cfg(debug_assertions)] +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 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) { + source_string.push_str("x") + } else { + source_string.push_str("o") + } + } + source_string.push_str("\n"); + } + write!(f, "{}", source_string) + } +} diff --git a/src/lib.rs b/src/lib.rs index 441ccd3..c976d85 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,6 +5,9 @@ mod data; use components::source_plate::SourcePlate; use dioxus::prelude::*; +#[cfg(debug_assertions)] +use data::*; + pub fn App(cx: Scope) -> Element { cx.render(rsx! { div { @@ -16,3 +19,17 @@ pub fn App(cx: Scope) -> Element { } }) } + +pub fn plate_test() { + let source = plate::Plate::new(plate::PlateType::Source, plate::PlateFormat::W96); + let destination = plate::Plate::new(plate::PlateType::Destination, plate::PlateFormat::W96); + + let transfer = transfer_region::TransferRegion { + source_plate: &source, + 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 + }; + println!("{}", transfer) +} diff --git a/src/main.rs b/src/main.rs index dc08439..7355031 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,9 @@ use plate_tool::App; +use plate_tool::plate_test; use wasm_logger; fn main() { - wasm_logger::init(wasm_logger::Config::default()); - dioxus_web::launch(App); +// wasm_logger::init(wasm_logger::Config::default()); +// dioxus_web::launch(App); + plate_test(); }