def test_save_tip_length(monkeypatch, clear_calibration): assert not os.path.exists(path(MOCK_HASH)) monkeypatch.setattr(labware, '_hash_labware_def', mock_hash_labware) test_labware = labware.Labware(minimalLabwareDef, Location(Point(0, 0, 0), 'deck')) calibrated_length = 22.0 labware.save_tip_length(test_labware, calibrated_length) assert os.path.exists(path(MOCK_HASH)) with open(path(MOCK_HASH)) as calibration_file: data = json.load(calibration_file) assert data['tipLength']['length'] == calibrated_length
def custom_mix(pipet, reagent, location, vol, rounds, blow_out, mix_height, x_offset, source_height = 3): ''' Function for mixing a given [vol] in the same [location] a x number of [rounds]. blow_out: Blow out optional [True,False] x_offset = [source, destination] source_height: height from bottom to aspirate mix_height: height from bottom to dispense ''' if mix_height == 0: mix_height = 3 pipet.aspirate(1, location=location.bottom( z=source_height).move(Point(x=x_offset[0])), rate=reagent.flow_rate_aspirate) for _ in range(rounds): pipet.aspirate(vol, location=location.bottom( z=source_height).move(Point(x=x_offset[0])), rate=reagent.flow_rate_aspirate) pipet.dispense(vol, location=location.bottom( z=mix_height).move(Point(x=x_offset[1])), rate=reagent.flow_rate_dispense) pipet.dispense(1, location=location.bottom( z=mix_height).move(Point(x=x_offset[1])), rate=reagent.flow_rate_dispense) if blow_out == True: pipet.blow_out(location.top(z=-2)) # Blow out
def move_vol_multichannel(pipet, reagent, source, dest, vol, air_gap_vol, x_offset, pickup_height, rinse, disp_height, blow_out, touch_tip): ''' x_offset: list with two values. x_offset in source and x_offset in destination i.e. [-1,1] pickup_height: height from bottom where volume rinse: if True it will do 2 rounds of aspirate and dispense before the tranfer disp_height: dispense height; by default it's close to the top (z=-2), but in case it is needed it can be lowered blow_out, touch_tip: if True they will be done after dispensing ''' # Rinse before aspirating if rinse == True: custom_mix(pipet, reagent, location=source, vol=vol, rounds=2, blow_out=True, mix_height=0, x_offset=x_offset) # SOURCE s = source.bottom(pickup_height).move(Point(x=x_offset[0])) pipet.aspirate(vol, s, rate=reagent.flow_rate_aspirate) # aspirate liquid if air_gap_vol != 0: # If there is air_gap_vol, switch pipette to slow speed pipet.aspirate(air_gap_vol, source.top(z=-2), rate=reagent.flow_rate_aspirate) # air gap # GO TO DESTINATION drop = dest.top(z=disp_height).move(Point(x=x_offset[1])) pipet.dispense(vol + air_gap_vol, drop, rate=reagent.flow_rate_dispense) # dispense all ctx.delay( seconds=reagent.delay) # pause for x seconds depending on reagent if blow_out == True: pipet.blow_out(dest.top(z=-2)) if touch_tip == True: pipet.touch_tip(speed=20, v_offset=-5)
def load_calibration(labware: Labware): """ Look up a calibration if it exists and apply it to the given labware. """ labware_offset_path = _get_labware_offset_path(labware) if labware_offset_path.exists(): calibration_data = _read_file(str(labware_offset_path)) offset_array = calibration_data['default']['offset'] offset = Point(x=offset_array[0], y=offset_array[1], z=offset_array[2]) labware.set_calibration(offset) if 'tipLength' in calibration_data.keys(): tip_length = calibration_data['tipLength']['length'] labware.tip_length = tip_length
def test_load_tip_length_calibration_data(monkeypatch, clear_tlc_calibration): assert not os.path.exists(tlc_path(PIPETTE_ID)) monkeypatch.setattr(labware, '_hash_labware_def', mock_hash_labware) test_labware = labware.Labware(minimalLabwareDef, Location(Point(0, 0, 0), 'deck')) tip_length = 22.0 test_data = labware.create_tip_length_data(test_labware, tip_length) labware.save_tip_length_calibration(PIPETTE_ID, test_data) result = labware.load_tip_length_calibration(PIPETTE_ID, test_labware) assert result == test_data[MOCK_HASH]
def wash(vol, source, mix_reps=15, resuspend=True): """ `wash` will perform bead washing for the extraction protocol. :param vol (float): The amount of volume to aspirate from each source and dispense to each well containing beads. :param source (List[Well]): A list of wells from where liquid will be aspirated. If the length of the source list > 1, `wash` automatically calculates the index of the source that should be accessed. :param mix_reps (int): The number of repititions to mix the beads with specified wash buffer (ignored if resuspend is False). :param resuspend (boolean): Whether to resuspend beads in wash buffer. """ if resuspend and magdeck.status == 'engaged': magdeck.disengage() num_trans = math.ceil(vol / 200) vol_per_trans = vol / num_trans for i, m in enumerate(mag_samples_m): _pick_up(m300) side = 1 if i % 2 == 0 else -1 loc = m.bottom(0.5).move(Point(x=side * m.geometry._width)) src = source[i // (12 // len(source))] m300.mix(3, 100, src) for n in range(num_trans): if m300.current_volume > 0: m300.dispense(m300.current_volume, src.top()) m300.transfer(vol_per_trans, src, m.top(), air_gap=20, new_tip='never') if n < num_trans - 1: # only air_gap if going back to source m300.air_gap(20) if resuspend: m300.mix(mix_reps, 150, loc) m300.blow_out(m.top()) m300.air_gap(20) _drop(m300) if magdeck.status == 'disengaged': magdeck.engage(height=mag_height) ctx.delay(minutes=settling_time, msg='Incubating on MagDeck for \ ' + str(settling_time) + ' minutes.') remove_supernatant(vol)
def elute(vol, parking_spots): """ `elute` will perform elution from the deepwell extraciton plate to the final clean elutions PCR plate to complete the extraction protocol. :param vol (float): The amount of volume to aspirate from the elution buffer source and dispense to each well containing beads. :param park (boolean): Whether to save sample-corresponding tips between adding elution buffer and transferring supernatant to the final clean elutions PCR plate. """ check_set(parking_spots) # resuspend beads in elution magdeck.disengage() for i, (m, spot) in enumerate(zip(mag_samples_m, parking_spots)): m300.pick_up_tip(spot) m300.aspirate(vol, elution_buffer[0]) m300.dispense(vol, m.bottom(1)) resuspend(m, mixreps, 40, x_mix_fraction=0.2, z_mix=1.0, dispense_height_rel=0) m300.blow_out(m.bottom(5)) m300.air_gap(5) m300.drop_tip(spot) if not TEST_MODE_BIND_INCUBATE: ctx.delay(minutes=5, msg='Incubating off MagDeck for 5 minutes.') magdeck.engage(engage_height) if not TEST_MODE_BEADS: ctx.delay(minutes=time_settling_minutes, msg=f'Incubating on \ MagDeck for {time_settling_minutes} minutes.') m300.flow_rate.aspirate /= 5 for i, (m, e, spot) in enumerate( zip(mag_samples_m, elution_samples_m, parking_spots)): m300.pick_up_tip(spot) m300.aspirate(vol_final_elution, m.bottom(0.8)) m300.dispense(vol_final_elution, e.bottom(5)) m300.move_to(e.bottom().move(Point(x=e.diameter / 2 * 0.8, z=7))) m300.blow_out(e.top(-2)) m300.air_gap(5) m300.drop_tip(spot)
def __init__(self, well_props: 'WellDefinition', parent: Location, display_name: str, has_tip: bool, api_level: APIVersion, name: str = None) -> None: """ Create a well, and track the Point corresponding to the top-center of the well (this Point is in absolute deck coordinates) :param display_name: a string that identifies a well. Used primarily for debug and test purposes. Should be unique and human-readable-- something like "Tip C3 of Opentrons 300ul Tiprack on Slot 5" or "Well D1 of Biorad 96 PCR Plate on Magnetic Module in Slot 1". This is created by the caller and passed in, so here it is just saved and made available. :param well_props: a dict that conforms to the json-schema for a Well :param parent: a :py:class:`.Location` Point representing the absolute position of the parent of the Well (usually the front-left corner of a labware) """ self._api_version = api_level self._display_name = display_name self._position\ = Point(well_props['x'], well_props['y'], well_props['z'] + well_props['depth']) + parent.point if not parent.labware: raise ValueError("Wells must have a parent") self._parent = parent.labware self._has_tip = has_tip self._shape = well_props['shape'] if well_props['shape'] == 'rectangular': self._length: Optional[float] = well_props['xDimension'] self._width: Optional[float] = well_props['yDimension'] self._diameter: Optional[float] = None elif well_props['shape'] == 'circular': self._length = None self._width = None self._diameter = well_props['diameter'] else: raise ValueError( 'Shape "{}" is not a supported well shape'.format( well_props['shape'])) self.max_volume = well_props['totalLiquidVolume'] self._depth = well_props['depth'] if name: self._name = name else: self._name = display_name
def elute(self, positions=None, transfer: bool = True, stage: str = "elute"): """Resuspend beads in elution""" if positions is None: positions = self.mag_samples_m self._m300.flow_rate.aspirate = self._elute_aspiration_rate for i, m in enumerate(positions): if self.run_stage("{} {}/{}".format(stage, i + 1, len(positions))): self.pick_up(self._m300) side = 1 if i % 2 == 0 else -1 loc = m.bottom(self._bottom_headroom_height).move(Point(x=side*2)) self._m300.aspirate(self._elution_vol, self.water) self._m300.air_gap(self._elute_air_gap) self._m300.dispense(self._elute_air_gap, m.top()) self._m300.dispense(self._elution_vol, loc) self._m300.mix(self._elute_mix_times, self._elute_mix_vol, loc) self._m300.touch_tip(v_offset=self._touch_tip_height) self._m300.air_gap(self._elute_air_gap) self.drop(self._m300) if self._elute_incubate and self.run_stage("{} incubate off".format(stage)): self.delay(self._wait_time_elute_off, self.get_msg_format("incubate on magdeck", self.get_msg("off"))) self._magdeck.engage(height=self._magheight) if self._elute_incubate and self.run_stage("{} incubate on".format(stage)): self.delay(self._wait_time_elute_on, self.get_msg_format("incubate on magdeck", self.get_msg("on"))) if transfer: for i, (m, e) in enumerate(zip( positions, self.elution_samples_m )): if self.run_stage("{} transfer {}/{}".format(stage, i + 1, len(positions))): self.pick_up(self._m300) side = -1 if i % 2 == 0 else 1 loc = m.bottom(self._bottom_headroom_height).move(Point(x=side*2)) self._m300.transfer(self._elution_vol, loc, e.bottom(self._elution_height), air_gap=self._elute_air_gap, new_tip='never') # m300.blow_out(e.top(-2)) self._m300.air_gap(self._elute_air_gap) self.drop(self._m300)
def elute(vol, park=True): # resuspend beads in elution if magdeck.status == 'enagaged': magdeck.disengage() for i, (m, spot) in enumerate(zip(mag_samples_m, parking_spots)): _pick_up(m300) side = 1 if i % 2 == 0 else -1 loc = m.bottom(0.5).move(Point(x=side * 2)) m300.aspirate(vol, elution_solution) m300.move_to(m.center()) m300.dispense(vol, loc) #m300.mix(mix_reps, 0.8*vol, loc) resuspend_pellet(m, m300, 180) m300.blow_out(m.bottom(5)) m300.air_gap(20) if park: m300.drop_tip(spot) else: _drop(m300) magdeck.engage(height=MAG_HEIGHT) ctx.delay(minutes=settling_time, msg='Incubating on MagDeck for \ ' + str(settling_time) + ' minutes.') for i, (m, e, spot) in enumerate( zip(mag_samples_m, elution_samples_m, parking_spots)): if park: _pick_up(m300, spot) else: _pick_up(m300) side = -1 if i % 2 == 0 else 1 loc = m.bottom(0.5).move(Point(x=side * 2)) m300.transfer(vol, loc, e.bottom(5), air_gap=20, new_tip='never') m300.blow_out(e.top(-2)) m300.air_gap(20) m300.drop_tip()
def elute(vol, park=True): # resuspend beads in elution for m, spot in zip(mag_samples_m, parking_spots): side_ind = int(m.display_name.split(' ')[0][1:]) side = -1 if side_ind % 2 == 0 else 1 pick_up(m300) loc = m.bottom(0.5).move(Point(x=side * 3)) m300.aspirate(vol, elution_solution) m300.move_to(m.center()) m300.dispense(vol, loc) m300.mix(10, 0.8 * vol, loc) m300.blow_out(m.bottom(5)) m300.air_gap(20) if park: m300.drop_tip(spot) else: drop(m300) ctx.delay(minutes=2, msg='Incubating off magnet at room temperature \ for 2 minutes') magdeck.engage(height=magheight) ctx.delay(minutes=2, msg='Incubating on magnet at room temperature \ for 2 minutes') for m, e, spot in zip(mag_samples_m, elution_samples_m, parking_spots): if park: pick_up(m300, spot) else: pick_up(m300) side_ind = int(m.display_name.split(' ')[0][1:]) side = 1 if side_ind % 2 == 0 else -1 loc = m.bottom(0.5).move(Point(x=side * 3)) m300.transfer(40, loc, e.bottom(5), air_gap=20, new_tip='never') m300.blow_out(e.top(-2)) m300.air_gap(20) m300.drop_tip()
def move_vol_multi(pipet, reagent, source, dest, vol, x_offset_source, x_offset_dest, pickup_height, blow_out, wait_time = 0, touch_tip = False, touch_tip_v_offset = 0, drop_height = -5, aspirate_with_x_scroll = False, dispense_bottom_air_gap_before = False): # SOURCE if dispense_bottom_air_gap_before and reagent.air_gap_vol_bottom: pipet.dispense(reagent.air_gap_vol_bottom, source.top(z = -2), rate = reagent.flow_rate_dispense) if reagent.air_gap_vol_top != 0: #If there is air_gap_vol, switch pipette to slow speed pipet.air_gap(reagent.air_gap_vol_top, height = 0) #air gap if aspirate_with_x_scroll: aspirate_with_x_scrolling(pip = pipet, volume = vol, src = source, pickup_height = pickup_height, rate = reagent.flow_rate_aspirate, start_x_offset_src = 0, stop_x_offset_src = x_offset_source) else: s = source.bottom(pickup_height).move(Point(x = x_offset_source)) pipet.aspirate(vol, s, rate = reagent.flow_rate_aspirate) # aspirate liquid if reagent.air_gap_vol_bottom != 0: #If there is air_gap_vol, switch pipette to slow speed pipet.air_gap(reagent.air_gap_vol_bottom, height = 0) #air gap # if wait_time != 0: # ctx.delay(seconds=wait_time, msg='Esperando durante ' + str(wait_time) + ' segundos.') # GO TO DESTINATION d = dest.top(z = drop_height).move(Point(x = x_offset_dest)) pipet.dispense(vol - reagent.disposal_volume + reagent.air_gap_vol_bottom, d, rate = reagent.flow_rate_dispense) if reagent.air_gap_vol_top != 0: pipet.dispense(reagent.air_gap_vol_top, dest.top(z = 0), rate = reagent.flow_rate_dispense) if blow_out == True: pipet.blow_out(dest.top(z = drop_height)) if touch_tip == True: pipet.touch_tip(speed = 20, v_offset = touch_tip_v_offset, radius=0.7) if wait_time != 0: ctx.delay(seconds=wait_time, msg='Esperando durante ' + str(wait_time) + ' segundos.')
def wash(self, vol: float, source, mix_reps: int, wash_name: str = "wash"): self.logger.info(self.msg_format("wash info", vol, wash_name, mix_reps)) self._m300.flow_rate.aspirate = self._default_aspiration_rate dispense_rate = self._m300.flow_rate.dispense self._magdeck.disengage() num_trans, vol_per_trans = uniform_divide(vol, self._wash_max_transfer_vol) for i, m in enumerate(self.mag_samples_m): if self.run_stage("{} {}/{}".format(wash_name, i + 1, len(self.mag_samples_m))): self.pick_up(self._m300) src = self.wash_getcol(i, len(self.mag_samples_m), source) for n in range(num_trans): if self._m300.current_volume > 0: self._m300.dispense(self._m300.current_volume, src.top()) self._m300.transfer(vol_per_trans, src, m.top(), air_gap=20, new_tip='never') if n < num_trans - 1: # only air_gap if going back to source self._m300.air_gap(self._wash_air_gap) # Mix self._m300.flow_rate.aspirate = self._wash_mix_aspiration_rate self._m300.flow_rate.dispense = self._wash_mix_dispense_rate if self._wash_mix_walk: a_locs = [m.bottom(self._bottom_headroom_height).move(Point(x=2*(-1 if i % 2 else +1), y=2*(2*j/(mix_reps - 1) - 1))) for j in range(mix_reps)] mix_walk(self._m300, mix_reps, self._wash_mix_vol, a_locs, speed=self._wash_mix_speed, logger=self.logger) else: loc = m.bottom(self._bottom_headroom_height).move(Point(x=2*(-1 if i % 2 else +1))) self._m300.mix(mix_reps, self._wash_mix_vol, loc) self._m300.flow_rate.aspirate = self._default_aspiration_rate self._m300.flow_rate.dispense = dispense_rate self._m300.air_gap(self._wash_air_gap) self.drop(self._m300) self._magdeck.engage(height=self._magheight) if self.run_stage("{} incubate".format(wash_name)): self.delay(self._wait_time_wash_on, self.get_msg_format("incubate on magdeck", self.get_msg("on"))) self.remove_supernatant(vol, stage="remove {}".format(wash_name))
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, P300M_GEN2_MAX_HEIGHT) 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, P300M_GEN2_MAX_HEIGHT) 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, P300M_GEN2_MAX_HEIGHT) 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, P300M_GEN2_MAX_HEIGHT) 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
async def test_motion(loop): hardware = API.build_hardware_simulator(loop=loop) ctx = papi.ProtocolContext(loop) ctx.connect(hardware) ctx.home() instr = ctx.load_instrument('p10_single', Mount.RIGHT) old_pos = await hardware.current_position(instr._mount) instr.home() assert instr.move_to(Location(Point(0, 0, 0), None)) is instr old_pos[Axis.X] = 0 old_pos[Axis.Y] = 0 old_pos[Axis.A] = 0 old_pos[Axis.C] = 2 assert await hardware.current_position(instr._mount) == old_pos
def test_pick_up_and_drop_tip(loop, get_labware_def): ctx = papi.ProtocolContext(loop) ctx.home() tiprack = ctx.load_labware('opentrons_96_tiprack_300ul', 1) tip_length = tiprack.tip_length mount = Mount.LEFT instr = ctx.load_instrument('p300_single', mount, tip_racks=[tiprack]) pipette: Pipette = ctx._hw_manager.hardware._attached_instruments[mount] model_offset = Point(*pipette.config.model_offset) assert pipette.critical_point() == model_offset target_location = tiprack['A1'].top() instr.pick_up_tip(target_location) assert not tiprack.wells()[0].has_tip overlap = instr.hw_pipette['tip_overlap'][tiprack.uri] new_offset = model_offset - Point(0, 0, tip_length - overlap) assert pipette.critical_point() == new_offset instr.drop_tip(target_location) assert tiprack.wells()[0].has_tip assert pipette.critical_point() == model_offset
async def _return_first_tip(self): first_pip = self._get_pipette_by_rank(PipetteRank.first) assert first_pip, \ 'cannot drop tip on first mount, pipette not present' mount = first_pip.mount z_value = float(self.pipettes[mount]['tip_length']) * 0.5 state_name = CalibrationCheckState.inspectingFirstTip return_pt = self._saved_points[getattr(CalibrationCheckState, state_name)] account_for_tip = return_pt - Point(0, 0, z_value) loc = Location(account_for_tip, None) await self._move(first_pip.mount, loc) await self._drop_tip(first_pip.mount)
def set_up_index_file(labware_offset_tempdir): deck = Deck() labware_list = [ 'nest_96_wellplate_2ml_deep', 'corning_384_wellplate_112ul_flat', 'geb_96_tiprack_1000ul', 'nest_12_reservoir_15ml'] for idx, name in enumerate(labware_list): parent = deck.position_for(idx+1) definition = labware.get_labware_definition(name) lw = labware.Labware(definition, parent) labware.save_calibration(lw, Point(0, 0, 0)) return labware_list
def _move_to_well(instruments: Instruments, loaded_labware: LoadedLabware, params: 'MoveToWellParams') -> None: pipette_id = params['pipette'] pipette = instruments[pipette_id] well = _get_well(loaded_labware, params) offset = params.get('offset', {}) offsetPoint = Point(offset.get('x', 0), offset.get('y', 0), offset.get('z', 0)) pipette.move_to(well.bottom().move(offsetPoint), force_direct=params.get('forceDirect'), minimum_z_height=params.get('minimumZHeight'))
def _drop(pip): nonlocal switch nonlocal drop_count side = 30 if switch else -18 drop_loc = ctx.loaded_labwares[12].wells()[0].top().move(Point(x=side)) pip.drop_tip(drop_loc) switch = not switch if pip.type == 'multi': drop_count += 8 else: drop_count += 1 if drop_count >= drop_threshold: # Setup for flashing lights notification to empty trash drop_count = 0
def test_well_init(): slot = Location(Point(1, 2, 3), 1) well_name = 'circular_well_json' has_tip = False well1 = labware.Well(test_data[well_name], slot, well_name, has_tip) assert well1._diameter == test_data[well_name]['diameter'] assert well1._length is None assert well1._width is None well2_name = 'rectangular_well_json' well2 = labware.Well(test_data[well2_name], slot, well2_name, has_tip) assert well2._diameter is None assert well2._length == test_data[well2_name]['xDimension'] assert well2._width == test_data[well2_name]['yDimension']
def wash_blot(): for wash, blot in zip(pin_wash_res.wells(), blot_locs): movement_locs = [ wash.center().move(Point(z=side*5)) for side in [-1, 1]] m300.move_to(wash.center()) ctx.max_speeds['X'] = 100 if wash_scheme == 'vertical movement': for _ in range(5): for m in movement_locs: m300.move_to(m) else: ctx.delay(seconds=5) m300.move_to(wash.center()) del ctx.max_speeds['X'] ctx.max_speeds['A'] = slow_speed_down ctx.max_speeds['Z'] = slow_speed_down m300.move_to(blot.move(Point(z=10))) m300.move_to(blot) ctx.delay(seconds=blot_dwell_time) del ctx.max_speeds['A'] del ctx.max_speeds['Z']
def set_up_index_file_temporary_directory(server_temp_directory): delete.clear_calibrations() deck = Deck() labware_list = [ 'nest_96_wellplate_2ml_deep', 'corning_384_wellplate_112ul_flat', 'geb_96_tiprack_1000ul', 'nest_12_reservoir_15ml', 'opentrons_96_tiprack_10ul'] for idx, name in enumerate(labware_list): parent = deck.position_for(idx+1) definition = labware.get_labware_definition(name) lw = labware.Labware(definition, parent) labware.save_calibration(lw, Point(0, 0, 0))
def elute(vol, park=True): # transfer samples for m, e in zip(mag_samples_m, elution_samples_m): pick_up(m300) side_ind = int(m.display_name.split(' ')[0][1:]) side = 1 if side_ind % 2 == 0 else -1 loc = m.bottom(LOCBOTTOM).move( Point(x=side * SIDEBOTTOM)) # mudei de LOCBOTTOM 3>2.5 fin = e.bottom(LOCBOTTOM) m300.transfer(vol, loc, fin, air_gap=20, new_tip='never') m300.mix(2, vol, fin) m300.blow_out(e.top(-2)) m300.air_gap(20) m300.drop_tip()
async def test_max_speeds(loop, monkeypatch): hardware = API.build_hardware_simulator(loop=loop) ctx = papi.ProtocolContext(loop) ctx.connect(hardware) ctx.home() mock_move = mock.Mock() monkeypatch.setattr(ctx._hw_manager.hardware, 'move_to', mock_move) instr = ctx.load_instrument('p10_single', Mount.RIGHT) instr.move_to(Location(Point(0, 0, 0), None)) assert all(kwargs['max_speeds'] == {} for args, kwargs in mock_move.call_args_list) mock_move.reset_mock() ctx.max_speeds['x'] = 10 instr.move_to(Location(Point(0, 0, 1), None)) assert all(kwargs['max_speeds'] == {Axis.X: 10} for args, kwargs in mock_move.call_args_list) mock_move.reset_mock() ctx.max_speeds['x'] = None instr.move_to(Location(Point(1, 0, 1), None)) assert all(kwargs['max_speeds'] == {} for args, kwargs in mock_move.call_args_list)
def test_gen2_module_transforms(): deck = Deck() tmod = module_geometry.load_module( module_geometry.TemperatureModuleModel.TEMPERATURE_V2, deck.position_for('1'), MAX_SUPPORTED_VERSION) assert tmod.labware_offset == Point(-1.45, -0.15, 80.09) tmod2 = module_geometry.load_module( module_geometry.TemperatureModuleModel.TEMPERATURE_V2, deck.position_for('3'), MAX_SUPPORTED_VERSION) assert tmod2.labware_offset == Point(1.15, -0.15, 80.09) mmod = module_geometry.load_module( module_geometry.MagneticModuleModel.MAGNETIC_V2, deck.position_for('1'), MAX_SUPPORTED_VERSION) assert mmod.labware_offset == Point(-1.175, -0.125, 82.25) mmod2 = module_geometry.load_module( module_geometry.MagneticModuleModel.MAGNETIC_V2, deck.position_for('3'), MAX_SUPPORTED_VERSION) assert mmod2.labware_offset == Point(1.425, -0.125, 82.25)
def jog(self, instrument, distance, axis): inst = instrument._instrument log.info('Jogging {} by {} in {}'.format(instrument.name, distance, axis)) self._set_state('moving') if ff.use_protocol_api_v2(): self._hardware.move_rel(Mount[inst.mount.upper()], Point(**{axis: distance})) else: calibration_functions.jog_instrument(instrument=inst, distance=distance, axis=axis, robot=inst.robot) self._set_state('ready')
def _drop(pip): nonlocal switch nonlocal drop_count side = 30 if switch else -18 drop_loc = ctx.loaded_labwares[12].wells()[0].top().move(Point(x=side)) pip.drop_tip(drop_loc) switch = not switch drop_count += 8 if drop_count == drop_threshold: m300.home() ctx.pause('Please empty tips from waste before resuming.') ctx.home() # home before continuing with protocol drop_count = 0
def test_thermocycler_semi_plate_configuration(loop): ctx = papi.ProtocolContext(loop) labware_name = 'nest_96_wellplate_100ul_pcr_full_skirt' mod = ctx.load_module('thermocycler', configuration='semi') assert mod._geometry.labware_offset == Point(-23.28, 82.56, 97.8) tc_labware = mod.load_labware(labware_name) other_labware = ctx.load_labware(labware_name, 2) without_first_two_cols = other_labware.wells()[16::] for tc_well, other_well in zip(tc_labware.wells(), without_first_two_cols): tc_well_name = tc_well.display_name.split()[0] other_well_name = other_well.display_name.split()[0] assert tc_well_name == other_well_name
def test_dispatch_commands(monkeypatch, loop, get_json_protocol_fixture): protocol_data = get_json_protocol_fixture('3', 'simple') command_log = [] mock_pipette = MockPipette(command_log) insts = {"pipetteId": mock_pipette} ctx = ProtocolContext(loop=loop) def mock_delay(seconds=0, minutes=0, msg=None): command_log.append(("delay", seconds + minutes * 60)) monkeypatch.setattr(ctx, 'delay', mock_delay) source_plate = ctx.load_labware('corning_96_wellplate_360ul_flat', '1') dest_plate = ctx.load_labware('corning_96_wellplate_360ul_flat', '2') tiprack = ctx.load_labware('opentrons_96_tiprack_10ul', '3') loaded_labware = { 'sourcePlateId': source_plate, 'destPlateId': dest_plate, 'tiprackId': tiprack, 'trashId': ctx.fixed_trash } execute_v3.dispatch_json(ctx, protocol_data, insts, loaded_labware) assert command_log == [ ("pick_up_tip", (tiprack['B1'], )), ("set: flow_rate.aspirate", (3, )), ("set: flow_rate.dispense", (3, )), ("set: flow_rate.blow_out", (3, )), ("aspirate", ( 5, source_plate['A1'].bottom(2), )), ("delay", 42), ("set: flow_rate.aspirate", (2.5, )), ("set: flow_rate.dispense", (2.5, )), ("set: flow_rate.blow_out", (2.5, )), ("dispense", ( 4.5, dest_plate['B1'].bottom(1), )), ("touch_tip", (dest_plate['B1'], ), { "v_offset": 0.33000000000000007 }), ("set: flow_rate.aspirate", (2, )), ("set: flow_rate.dispense", (2, )), ("set: flow_rate.blow_out", (2, )), ("blow_out", (dest_plate['B1'], )), ("move_to", (ctx.deck.position_for('5').move(Point(1, 2, 3)), ), { "force_direct": None, "minimum_z_height": None }), ("drop_tip", (ctx.fixed_trash['A1'], )) ]