Structs for transfers, lots of fixing
This commit is contained in:
		
							parent
							
								
									a2d406e9c4
								
							
						
					
					
						commit
						ed8a11e8c7
					
				| 
						 | 
				
			
			@ -1,2 +1,2 @@
 | 
			
		|||
pub mod plate;
 | 
			
		||||
pub mod region;
 | 
			
		||||
pub mod transfer_region;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										17
									
								
								src/lib.rs
								
								
								
								
							
							
						
						
									
										17
									
								
								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)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue