Precompute in calculate_map
	
		
			
	
		
	
	
		
			
				
	
				Gitea Scan/plate-tool/pipeline/head This commit looks good
				
					Details
				
			
		
	
				
					
				
			
				
	
				Gitea Scan/plate-tool/pipeline/head This commit looks good
				
					Details
				
			
		
	should help performance a wee bit
This commit is contained in:
		
							parent
							
								
									3d8445ec82
								
							
						
					
					
						commit
						f50db96697
					
				| 
						 | 
					@ -182,61 +182,98 @@ impl TransferRegion {
 | 
				
			||||||
                    let Well { row: i, col: j } = w;
 | 
					                    let Well { row: i, col: j } = w;
 | 
				
			||||||
                    if source_wells.contains(&w) {
 | 
					                    if source_wells.contains(&w) {
 | 
				
			||||||
                        let possible_destination_wells = create_dense_rectangle(c1, c2);
 | 
					                        let possible_destination_wells = create_dense_rectangle(c1, c2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        // Destination upper-left, bottom-right
 | 
				
			||||||
                        let (d_ul, d_br) = standardize_rectangle(c1, c2);
 | 
					                        let (d_ul, d_br) = standardize_rectangle(c1, c2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        // Source upper-left, bottom-right
 | 
				
			||||||
                        let (s_ul, s_br) =
 | 
					                        let (s_ul, s_br) =
 | 
				
			||||||
                            standardize_rectangle(&source_corners.0, &source_corners.1);
 | 
					                            standardize_rectangle(&source_corners.0, &source_corners.1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        // Get base size of source region before interleave
 | 
				
			||||||
                        let s_dims = (
 | 
					                        let s_dims = (
 | 
				
			||||||
                            s_br.row.checked_sub(s_ul.row).unwrap() + 1,
 | 
					                            s_br.row.checked_sub(s_ul.row).unwrap() + 1,
 | 
				
			||||||
                            s_br.col.checked_sub(s_ul.col).unwrap() + 1,
 | 
					                            s_br.col.checked_sub(s_ul.col).unwrap() + 1,
 | 
				
			||||||
                        );
 | 
					                        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        // Get base size of destination region before interleave
 | 
				
			||||||
                        let d_dims = (
 | 
					                        let d_dims = (
 | 
				
			||||||
                            d_br.row.checked_sub(d_ul.row).unwrap() + 1,
 | 
					                            d_br.row.checked_sub(d_ul.row).unwrap() + 1,
 | 
				
			||||||
                            d_br.col.checked_sub(d_ul.col).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 = (
 | 
					                        let number_used_src_wells = (
 | 
				
			||||||
                            // Number of used source wells
 | 
					                            (s_dims.0 + il_source_uabs.0 - 1)
 | 
				
			||||||
                            (s_dims.0 + il_source.0.unsigned_abs() - 1)
 | 
					                                .div_euclid(il_source_uabs.0),
 | 
				
			||||||
                                .div_euclid(il_source.0.unsigned_abs()),
 | 
					                            (s_dims.1 + il_source_uabs.1 - 1)
 | 
				
			||||||
                            (s_dims.1 + il_source.1.unsigned_abs() - 1)
 | 
					                                .div_euclid(il_source_uabs.1),
 | 
				
			||||||
                                .div_euclid(il_source.1.unsigned_abs()),
 | 
					 | 
				
			||||||
                        );
 | 
					                        );
 | 
				
			||||||
                        let count = (
 | 
					
 | 
				
			||||||
                            // How many times can we replicate?
 | 
					                        // How many times can we replicate in each direction?
 | 
				
			||||||
                            if il_dest.0.unsigned_abs() == 0 {
 | 
					                        // 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
 | 
					                                    1
 | 
				
			||||||
                                } else {
 | 
					                                } else {
 | 
				
			||||||
                                    (1..)
 | 
					                                    (1..)
 | 
				
			||||||
                                        .position(|n| {
 | 
					                                        .position(|n| {
 | 
				
			||||||
                                        (n * number_used_src_wells.0 * il_dest.0.unsigned_abs())
 | 
					                                            (n * replicate_base_size.0)
 | 
				
			||||||
                                            .saturating_sub(il_dest.0.unsigned_abs())
 | 
					                                                .saturating_sub(il_dest_uabs.0)
 | 
				
			||||||
                                                + 1
 | 
					                                                + 1
 | 
				
			||||||
                                                > d_dims.0
 | 
					                                                > d_dims.0
 | 
				
			||||||
                                        })
 | 
					                                        })
 | 
				
			||||||
                                        .unwrap() as u8
 | 
					                                        .unwrap() as u8
 | 
				
			||||||
                                },
 | 
					                                },
 | 
				
			||||||
                            if il_dest.1.unsigned_abs() == 0 {
 | 
					                                if il_dest_uabs.1 == 0 {
 | 
				
			||||||
                                    1
 | 
					                                    1
 | 
				
			||||||
                                } else {
 | 
					                                } else {
 | 
				
			||||||
                                    (1..)
 | 
					                                    (1..)
 | 
				
			||||||
                                        .position(|n| {
 | 
					                                        .position(|n| {
 | 
				
			||||||
                                        (n * number_used_src_wells.1 * il_dest.1.unsigned_abs())
 | 
					                                            (n * replicate_base_size.1)
 | 
				
			||||||
                                            .saturating_sub(il_dest.1.unsigned_abs())
 | 
					                                                .saturating_sub(il_dest_uabs.1)
 | 
				
			||||||
                                                + 1
 | 
					                                                + 1
 | 
				
			||||||
                                                > d_dims.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
 | 
					                        let i = i
 | 
				
			||||||
                            .saturating_sub(s_ul.row)
 | 
					                            .saturating_sub(s_ul.row)
 | 
				
			||||||
                            .saturating_div(il_source.0.unsigned_abs());
 | 
					                            .saturating_div(il_source_uabs.0);
 | 
				
			||||||
                        let j = j
 | 
					                        let j = j
 | 
				
			||||||
                            .saturating_sub(s_ul.col)
 | 
					                            .saturating_sub(s_ul.col)
 | 
				
			||||||
                            .saturating_div(il_source.1.unsigned_abs());
 | 
					                            .saturating_div(il_source_uabs.1);
 | 
				
			||||||
                        let checked_il_dest = (u8::max(il_dest.0.unsigned_abs(), 1u8),
 | 
					
 | 
				
			||||||
                                                u8::max(il_dest.1.unsigned_abs(), 1u8));
 | 
					                        // 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 row_modulus = number_used_src_wells.0 * checked_il_dest.0;
 | 
				
			||||||
                        let column_modulus = number_used_src_wells.1 * checked_il_dest.1;
 | 
					                        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(
 | 
					                        Some(
 | 
				
			||||||
                            possible_destination_wells
 | 
					                            possible_destination_wells
 | 
				
			||||||
| 
						 | 
					@ -244,24 +281,22 @@ impl TransferRegion {
 | 
				
			||||||
                                .filter(|Well { row: x, .. }| {
 | 
					                                .filter(|Well { row: x, .. }| {
 | 
				
			||||||
                                    x.checked_sub(d_ul.row).unwrap()
 | 
					                                    x.checked_sub(d_ul.row).unwrap()
 | 
				
			||||||
                                        % row_modulus // Counter along x
 | 
					                                        % row_modulus // Counter along x
 | 
				
			||||||
                                    == (il_dest.0.unsigned_abs() *i)
 | 
					                                    == residue_class.0
 | 
				
			||||||
                                        % row_modulus
 | 
					 | 
				
			||||||
                                })
 | 
					                                })
 | 
				
			||||||
                                .filter(|Well { col: y, .. }| {
 | 
					                                .filter(|Well { col: y, .. }| {
 | 
				
			||||||
                                    y.checked_sub(d_ul.col).unwrap()
 | 
					                                    y.checked_sub(d_ul.col).unwrap()
 | 
				
			||||||
                                        % column_modulus // Counter along u
 | 
					                                        % column_modulus // Counter along u
 | 
				
			||||||
                                    == (il_dest.1.unsigned_abs() *j)
 | 
					                                    == residue_class.1
 | 
				
			||||||
                                        % column_modulus
 | 
					 | 
				
			||||||
                                })
 | 
					                                })
 | 
				
			||||||
                                .filter(|Well { row: x, col: y }| {
 | 
					                                .filter(|Well { row: x, col: y }| {
 | 
				
			||||||
                                    // How many times have we replicated? < How many are we allowed
 | 
					                                    // How many times have we replicated? < How many are we allowed
 | 
				
			||||||
                                    // to replicate?
 | 
					                                    // to replicate?
 | 
				
			||||||
                                    x.checked_sub(d_ul.row).unwrap().div_euclid(
 | 
					                                    x.checked_sub(d_ul.row).unwrap().div_euclid(row_modulus)
 | 
				
			||||||
                                        row_modulus
 | 
					                                        < count.0
 | 
				
			||||||
                                    ) < count.0
 | 
					                                        && y.checked_sub(d_ul.col)
 | 
				
			||||||
                                        && y.checked_sub(d_ul.col).unwrap().div_euclid(
 | 
					                                            .unwrap()
 | 
				
			||||||
                                            column_modulus
 | 
					                                            .div_euclid(column_modulus)
 | 
				
			||||||
                                        ) < count.1
 | 
					                                            < count.1
 | 
				
			||||||
                                })
 | 
					                                })
 | 
				
			||||||
                                .collect(),
 | 
					                                .collect(),
 | 
				
			||||||
                        )
 | 
					                        )
 | 
				
			||||||
| 
						 | 
					@ -319,8 +354,8 @@ impl TransferRegion {
 | 
				
			||||||
                    return Err("Source region is out-of-bounds! (Too wide)");
 | 
					                    return Err("Source region is out-of-bounds! (Too wide)");
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if il_dest == (0,0) {
 | 
					                if il_dest == (0, 0) {
 | 
				
			||||||
                    return Err("Refusing to pool both dimensions in a rectangular transfer!\nPlease select a point in the destination plate.")
 | 
					                    return Err("Refusing to pool both dimensions in a rectangular transfer!\nPlease select a point in the destination plate.");
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            Region::Custom(_) => return Ok(()),
 | 
					            Region::Custom(_) => return Ok(()),
 | 
				
			||||||
| 
						 | 
					@ -343,7 +378,8 @@ fn create_dense_rectangle(c1: &Well, c2: &Well) -> Vec<Well> {
 | 
				
			||||||
    // Creates a vector of every point between two corners
 | 
					    // Creates a vector of every point between two corners
 | 
				
			||||||
    let (c1, c2) = standardize_rectangle(c1, c2);
 | 
					    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 i in c1.row..=c2.row {
 | 
				
			||||||
        for j in c1.col..=c2.col {
 | 
					        for j in c1.col..=c2.col {
 | 
				
			||||||
            points.push(Well { row: i, col: j });
 | 
					            points.push(Well { row: i, col: j });
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue