def test_direct_cp(): deck = Deck() trough = labware.load(trough_name, deck.position_for(1)) lw1 = labware.load(labware_name, deck.position_for(2)) # when moving from no origin location to a centered labware we should # start in default cp from_nothing = plan_moves(Location(Point(50, 50, 50), None), trough.wells()[0].top(), deck) check_arc_basic(from_nothing, Location(Point(50, 50, 50), None), trough.wells()[0].top()) assert from_nothing[0][1] is None assert from_nothing[1][1] == CriticalPoint.XY_CENTER assert from_nothing[2][1] == CriticalPoint.XY_CENTER # when moving from an origin with a centered labware to a dest with a # centered labware we should stay in centered the entire time, whether # arc from_centered_arc = plan_moves(trough.wells()[0].top(), trough.wells()[1].top(), deck) check_arc_basic(from_centered_arc, trough.wells()[0].top(), trough.wells()[1].top()) assert from_centered_arc[0][1] == CriticalPoint.XY_CENTER assert from_centered_arc[1][1] == CriticalPoint.XY_CENTER assert from_centered_arc[2][1] == CriticalPoint.XY_CENTER # or direct from_centered_direct = plan_moves(trough.wells()[0].top(), trough.wells()[1].bottom(), deck) assert from_centered_direct[0][1] == CriticalPoint.XY_CENTER # when moving from centered to normal, only the first move should be # centered to_normal = plan_moves(trough.wells()[0].top(), lw1.wells()[0].top(), deck) check_arc_basic(to_normal, trough.wells()[0].top(), lw1.wells()[0].top()) assert to_normal[0][1] == CriticalPoint.XY_CENTER assert to_normal[1][1] is None assert to_normal[2][1] is None
def test_arc_lower_minimum_z_height(): deck = Deck() lw1 = labware.load(labware_name, deck.position_for(1)) tall_z = 100 minimum_z_height = 42 old_top = lw1.wells()[0].top() tall_point = old_top.point._replace(z=tall_z) tall_top = old_top._replace(point=tall_point) to_tall = plan_moves(lw1.wells()[2].top(), tall_top, deck, 7.0, 15.0, False, minimum_z_height=minimum_z_height) check_arc_basic(to_tall, lw1.wells()[2].top(), tall_top) assert to_tall[0][0].z == tall_z from_tall = plan_moves(tall_top, lw1.wells()[3].top(), deck, 7.0, 15.0, minimum_z_height=minimum_z_height) check_arc_basic(from_tall, tall_top, lw1.wells()[3].top()) assert from_tall[0][0].z == tall_z no_well = tall_top._replace(labware=lw1) from_tall_lw = plan_moves(no_well, lw1.wells()[4].bottom(), deck, 7.0, 15.0) check_arc_basic(from_tall_lw, no_well, lw1.wells()[4].bottom())
def test_basic_arc(): deck = Deck() lw1 = labware.load(labware_name, deck.position_for(1)) lw2 = labware.load(labware_name, deck.position_for(2)) deck[1] = lw1 deck[2] = lw2 # same-labware moves should use the smaller safe z same_lw = plan_moves(lw1.wells()[0].top(), lw1.wells()[8].bottom(), deck, P300M_GEN2_MAX_HEIGHT, 7.0, 15.0) check_arc_basic(same_lw, lw1.wells()[0].top(), lw1.wells()[8].bottom()) assert same_lw[0][0].z == lw1.wells()[0].top().point.z + 7.0 # different-labware moves, or moves with no labware attached, # should use the larger safe z and the global z different_lw = plan_moves(lw1.wells()[0].top(), lw2.wells()[0].bottom(), deck, P300M_GEN2_MAX_HEIGHT, 7.0, 15.0) check_arc_basic(different_lw, lw1.wells()[0].top(), lw2.wells()[0].bottom()) assert different_lw[0][0].z == deck.highest_z + 15.0
def test_no_labware_loc(): labware_def = labware.get_labware_definition(labware_name) deck = Deck() lw1 = labware.load(labware_name, deck.position_for(1)) lw2 = labware.load(labware_name, deck.position_for(2)) # Various flavors of locations without labware should work no_lw = lw1.wells()[0].top()._replace(labware=None) no_from = plan_moves(no_lw, lw2.wells()[0].bottom(), deck, 7.0, 15.0) check_arc_basic(no_from, no_lw, lw2.wells()[0].bottom()) assert no_from[0][0].z == deck.highest_z + 15.0 no_to = plan_moves(lw1.wells()[0].bottom(), no_lw, deck, 7.0, 15.0) check_arc_basic(no_to, lw1.wells()[0].bottom(), no_lw) assert no_from[0][0].z == deck.highest_z + 15.0 no_well = lw1.wells()[0].top()._replace(labware=lw1) no_from_well = plan_moves(no_well, lw1.wells()[1].top(), deck, 7.0, 15.0) check_arc_basic(no_from_well, no_well, lw1.wells()[1].top()) assert no_from_well[0][0].z\ == labware_def['dimensions']['zDimension'] + 7.0 no_to_well = plan_moves(lw1.wells()[1].top(), no_well, deck, 7.0, 15.0) check_arc_basic(no_to_well, lw1.wells()[1].top(), no_well) assert no_to_well[0][0].z\ == labware_def['dimensions']['zDimension'] + 7.0
def test_instr_max_height(): deck = Deck() trough = labware.load(trough_name, deck.position_for(1)) trough2 = labware.load(trough_name, deck.position_for(2)) deck[1] = trough deck[2] = trough2 # if the highest deck height is between 1 mm and 10 mm below # the max instrument achievable height, we use the max instrument # height as the safe height instr_max_height = trough.wells()[0].top().point.z + 1 moves1 = plan_moves( trough.wells()[0].top(), trough2.wells()[0].top(), deck, round(instr_max_height, 2), 7.0, 15.0) assert moves1[0][0].z == round(instr_max_height, 2) # if the highest deck height is > 10 mm below the max instrument # height, we use the lw_z_margin instead instr_max_height = trough.wells()[0].top().point.z + 30 moves2 = plan_moves( trough.wells()[0].top(), trough2.wells()[0].top(), deck, round(instr_max_height, 2), 7.0, 15.0) assert moves2[0][0].z ==\ round(trough.wells()[0].top().point.z, 2) + 15.0 # it fails if the highest deck height is less than 1 mm below # the max instr achievable height instr_max_height = trough.wells()[0].top().point.z with pytest.raises(Exception): plan_moves( trough.wells()[0].top(), trough2.wells()[0].top(), deck, round(instr_max_height, 2), 7.0, 15.0)
def test_direct_movs(): deck = Deck() lw1 = labware.load(labware_name, deck.position_for(1)) same_place = plan_moves(lw1.wells()[0].top(), lw1.wells()[0].top(), deck) assert same_place == [(lw1.wells()[0].top().point, None)] same_well = plan_moves(lw1.wells()[0].top(), lw1.wells()[0].bottom(), deck) assert same_well == [(lw1.wells()[0].bottom().point, None)]
def test_direct_movs(): deck = Deck() lw1 = labware.load(labware_name, deck.position_for(1)) same_place = plan_moves( lw1.wells()[0].top(), lw1.wells()[0].top(), deck, instr_max_height=P300M_GEN2_MAX_HEIGHT) assert same_place == [(lw1.wells()[0].top().point, None)] same_well = plan_moves( lw1.wells()[0].top(), lw1.wells()[0].bottom(), deck, instr_max_height=P300M_GEN2_MAX_HEIGHT) assert same_well == [(lw1.wells()[0].bottom().point, None)]
def test_force_direct(): deck = Deck() lw1 = labware.load(labware_name, deck.position_for(1)) lw2 = labware.load(labware_name, deck.position_for(2)) # same-labware moves should move direct same_lw = plan_moves(lw1.wells()[0].top(), lw1.wells()[8].bottom(), deck, P300M_GEN2_MAX_HEIGHT, 7.0, 15.0, force_direct=True) assert same_lw == [(lw1.wells()[8].bottom().point, None)] # different-labware moves should move direct different_lw = plan_moves(lw1.wells()[0].top(), lw2.wells()[0].bottom(), deck, P300M_GEN2_MAX_HEIGHT, 7.0, 15.0, force_direct=True) assert different_lw == [(lw2.wells()[0].bottom().point, None)]
def test_direct_minimum_z_height(): deck = Deck() lw1 = labware.load(labware_name, deck.position_for(1)) from_loc = lw1.wells()[0].bottom().move(Point(x=-2)) to_loc = lw1.wells()[0].bottom().move(Point(x=2)) zmo = 150 # This would normally be a direct move since it’s inside the same well, # but we want to check that we override it into an arc moves = plan_moves(from_loc, to_loc, deck, minimum_z_height=zmo) assert len(moves) == 3 assert moves[0][0].z == zmo # equals zmo b/c 150 is max of all safe z's check_arc_basic(moves, from_loc, to_loc)
def test_no_labware_loc(labware_offset_tempdir): labware_def = labware.get_labware_definition(labware_name) deck = Deck() lw1 = labware.load(labware_name, deck.position_for(1)) lw2 = labware.load(labware_name, deck.position_for(2)) deck[1] = lw1 deck[2] = lw2 # Various flavors of locations without labware should work no_lw = lw1.wells()[0].top()._replace(labware=None) no_from = plan_moves(no_lw, lw2.wells()[0].bottom(), deck, P300M_GEN2_MAX_HEIGHT, 7.0, 15.0) check_arc_basic(no_from, no_lw, lw2.wells()[0].bottom()) assert no_from[0][0].z == deck.highest_z + 15.0 no_to = plan_moves(lw1.wells()[0].bottom(), no_lw, deck, P300M_GEN2_MAX_HEIGHT, 7.0, 15.0) check_arc_basic(no_to, lw1.wells()[0].bottom(), no_lw) assert no_from[0][0].z == deck.highest_z + 15.0 no_well = lw1.wells()[0].top()._replace(labware=lw1) no_from_well = plan_moves(no_well, lw1.wells()[1].top(), deck, P300M_GEN2_MAX_HEIGHT, 7.0, 15.0) check_arc_basic(no_from_well, no_well, lw1.wells()[1].top()) no_from_well_height = no_from_well[0][0].z lw_height_expected = labware_def['dimensions']['zDimension'] + 7 assert no_from_well_height == lw_height_expected no_to_well = plan_moves(lw1.wells()[1].top(), no_well, deck, P300M_GEN2_MAX_HEIGHT, 7.0, 15.0) check_arc_basic(no_to_well, lw1.wells()[1].top(), no_well) no_to_well_height = no_to_well[0][0].z assert no_to_well_height == lw_height_expected
async def _move(self, pipette_id: UUID, request_position: Location): # determine current location mount = self._get_mount(pipette_id) from_pt = await self.hardware.gantry_position(mount) from_loc = Location(from_pt, None) max_height = self.hardware.get_instrument_max_height(mount) moves = geometry.plan_moves(from_loc, request_position, self._deck, max_height) for move in moves: await self.hardware.move_to(mount, move[0], move[1])