Example #1
0
 def jog(self, instrument, distance, axis):
     inst = instrument._instrument
     log.info('Jogging {} by {} in {}'.format(instrument.name, distance,
                                              axis))
     self._set_state('moving')
     if instrument._context:
         try:
             self._hardware.move_rel(Mount[inst.mount.upper()],
                                     Point(**{axis: distance}),
                                     check_bounds=MotionChecks.HIGH)
         except OutOfBoundsMove:
             log.exception('Out of bounds jog')
     else:
         calibration_functions.jog_instrument(instrument=inst,
                                              distance=distance,
                                              axis=axis,
                                              robot=inst.robot)
     self._set_state('ready')
 def remove_supernatant(vol):
     ctx.comment('\n\n\n~~~~~~~~REMOVING SUPERNATANT~~~~~~~~\n')
     pip.pick_up_tip()
     pip.flow_rate.aspirate = 45
     for i, col in enumerate(working_cols):
         side = -1 if i % 2 == 0 else 1
         aspirate_loc = col.bottom(z=asp_height).move(
             Point(x=(col.length / 2 - length_from_side) * side))
         pip.transfer(vol,
                      aspirate_loc,
                      waste.bottom(z=25),
                      new_tip='never'
                      # blow_out=True,
                      # blowout_location='destination well'
                      )
         # pip.blow_out()
     pip.flow_rate.aspirate = 92
     pip.drop_tip()
Example #3
0
def test_module_load_labware(module_name):
    labware_name = 'corning_96_wellplate_360ul_flat'
    labware_def = labware.get_labware_definition(labware_name)
    model = module_geometry.resolve_module_model(module_name)
    mod = module_geometry.load_module(model, Location(Point(0, 0, 0), 'test'))
    old_z = mod.highest_z
    lw = labware.load_from_definition(labware_def, mod.location)
    mod.add_labware(lw)
    assert mod.labware == lw
    assert mod.highest_z ==\
        (mod.location.point.z
         + labware_def['dimensions']['zDimension']
         + mod._over_labware)
    with pytest.raises(AssertionError):
        mod.add_labware(lw)
    mod.reset_labware()
    assert mod.labware is None
    assert mod.highest_z == old_z
Example #4
0
def test_previous_tip():
    labware_name = 'opentrons_96_tiprack_300ul'
    labware_def = labware.get_labware_definition(labware_name)
    tiprack = labware.Labware(labware_def, Location(Point(0, 0, 0),
                                                    'Test Slot'))
    # If all wells are used, we can't get a previous tip
    assert tiprack.previous_tip() is None
    # If one well is empty, wherever it is, we can get a slot
    tiprack.wells()[5].has_tip = False
    assert tiprack.previous_tip() is tiprack.wells()[5]
    # But not if we ask for more slots than are available
    assert tiprack.previous_tip(2) is None
    tiprack.wells()[7].has_tip = False
    # And those available wells have to be contiguous
    assert tiprack.previous_tip(2) is None
    # But if they are, we're good
    tiprack.wells()[6].has_tip = False
    assert tiprack.previous_tip(3) is tiprack.wells()[5]
def aspirate_wit_scrolling(pip,
                           volume,
                           src,
                           start_height=0,
                           stop_height=0,
                           x_offset_src=0):

    start_point = src._depth if start_height == 0 else start_height

    stop_point = 0.0 if stop_height == 0 else stop_height

    max_asp = volume / pip.min_volume

    inc_step = (start_point - stop_point) / max_asp

    for h in reversed(np.arange(stop_point, start_point, inc_step)):
        s = src.bottom(h).move(Point(x=x_offset_src))
        pip.aspirate(volume=pip.min_volume, location=s)
 def distribute_custom(pipette, volume, src, dest, waste_pool, pickup_height, extra_dispensal, dest_x_offset, disp_height=0):
     # Custom distribute function that allows for blow_out in different location and adjustement of touch_tip
     pipette.aspirate((len(dest) * volume) +
                      extra_dispensal, src.bottom(pickup_height))
     pipette.touch_tip(speed=20, v_offset=-5)
     pipette.move_to(src.top(z=5))
     pipette.aspirate(5)  # air gap
     for d in dest:
         pipette.dispense(5, d.top())
         drop = d.top(z = disp_height).move(Point(x = dest_x_offset))
         pipette.dispense(volume, drop)
         pipette.move_to(d.top(z=5))
         pipette.aspirate(5)  # air gap
     try:
         pipette.blow_out(waste_pool.wells()[0].bottom(pickup_height + 3))
     except:
         pipette.blow_out(waste_pool.bottom(pickup_height + 3))
     return (len(dest) * volume)
    def step1():

        for i in range(len(pcr_elution_buffer_rack.columns())):

            if not m20.hw_pipette['has_tip']:
                pick_up(m20, tips20)

            src_pcr = pcr_elution_buffer_rack.columns()[i][0]

            dest_pcr = [elution_dest_rack.columns()[i][0]]

            distribute_custom(pip=m20,
                              reagent=pcr_reagent,
                              tube_type=pcr_tube,
                              volume=10,
                              src=src_pcr,
                              dest=dest_pcr,
                              max_volume=20,
                              extra_dispensal=0,
                              touch_tip_aspirate=False,
                              touch_tip_dispense=False)

            custom_mix(pip=m20,
                       reagent=pcr_reagent,
                       repetitions=2,
                       volume=10,
                       location=elution_dest_rack.columns()[i][0],
                       mix_height=2.5,
                       source_height=2.5)

            m20.touch_tip(radius=1.0,
                          v_offset=-5,
                          speed=pcr_reagent.touch_tip_dispense_speed)

            pcr_tube.actual_volume = 5

            x = elution_dest_rack.columns()[i][0].top().point.x
            y = 345.65
            z = 120

            loc = Location(Point(x, y, z), 'Warning')
            m20.move_to(location=loc)

            drop(m20)
    def remove_supernatant(vol, park=False):
        """
        `remove_supernatant` will transfer supernatant from the deepwell
        extraction plate to the liquid waste reservoir.
        :param vol (float): The amount of volume to aspirate from all deepwell
                            sample wells and dispense in the liquid waste.
        :param park (boolean): Whether to pick up sample-corresponding tips
                               in the 'parking rack' or to pick up new tips.
        """
        def _waste_track(vol):
            nonlocal waste_vol
            if waste_vol + vol >= waste_threshold:
                ctx.pause('Please empty liquid waste (slot 11) before \
resuming.')

                ctx.home()  # home before continuing with protocol
                waste_vol = 0
            waste_vol += vol

        m300.flow_rate.aspirate = 30
        num_trans = math.ceil(vol / 200)
        vol_per_trans = vol / num_trans
        for i, (m, spot) in enumerate(zip(mag_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))
            for _ in range(num_trans):
                _waste_track(vol_per_trans * 8)
                if m300.current_volume > 0:
                    # void air gap if necessary
                    m300.dispense(m300.current_volume, m.top())
                m300.move_to(m.center())
                m300.transfer(vol_per_trans,
                              loc,
                              waste,
                              new_tip='never',
                              air_gap=20)
                m300.blow_out(waste)
                m300.air_gap(20)
            _drop(m300)
        m300.flow_rate.aspirate = 150
Example #9
0
def test_back_compat():
    labware_name = 'corning_96_wellplate_360ul_flat'
    labware_def = labware.get_labware_definition(labware_name)
    lw = labware.Labware(labware_def, Location(Point(0, 0, 0), 'Test Slot'))

    # Note that this test uses the display name of wells to test for equality,
    # because dimensional parameters could be subject to modification through
    # calibration, whereas here we are testing for "identity" in a way that is
    # related to the combination of well name, labware name, and slot name
    well_a1_name = repr(lw.wells_by_name()['A1'])
    well_b2_name = repr(lw.wells_by_name()['B2'])
    well_c3_name = repr(lw.wells_by_name()['C3'])

    w2 = lw.well(0)
    assert repr(w2) == well_a1_name

    w3 = lw.well('A1')
    assert repr(w3) == well_a1_name

    w4 = lw.wells('B2')
    assert repr(w4[0]) == well_b2_name

    w5 = lw.wells(9, 21, 25, 27)
    assert len(w5) == 4
    assert repr(w5[0]) == well_b2_name

    w6 = lw.wells('A1', 'B2', 'C3')
    assert all([
        repr(well[0]) == well[1]
        for well in zip(w6, [well_a1_name, well_b2_name, well_c3_name])
    ])

    w7 = lw.rows('A')
    assert len(w7) == 1
    assert repr(w7[0][0]) == well_a1_name

    w8 = lw.rows('A', 'C')
    assert len(w8) == 2
    assert repr(w8[0][0]) == well_a1_name
    assert repr(w8[1][2]) == well_c3_name

    w11 = lw.columns('2', '3', '6')
    assert len(w11) == 3
    assert repr(w11[1][2]) == well_c3_name
    def stop_reaction(vol, source, mix_reps=6, park=True, resuspend=True):

        if resuspend and magdeck.status == 'engaged':
            magdeck.disengage()

        num_trans = math.ceil(vol / 200)
        vol_per_trans = vol / num_trans
        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))
            src = source[i // (12 // len(source))]
            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, 50, loc)
                resuspend_pellet(m, m300, 180)
            m300.blow_out(m.top())
            m300.air_gap(20)
            if park:
                m300.drop_tip(spot)
            else:
                _drop(m300)

        ctx.pause(
            'Incubating for 10 minutes with occasional mixing for stop reaction'
        )

        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, park=park)
Example #11
0
def _load_from_v2(definition: Dict[str, Any], parent: Location,
                  api_level: APIVersion,
                  configuration: GenericConfiguration) -> ModuleGeometry:
    """ Load a module geometry from a v2 definition.

    The definition should be schema checked before being passed to this
     function; all definitions passed here are assumed to be valid.
    """
    pre_transform = np.array((definition['labwareOffset']['x'],
                              definition['labwareOffset']['y'], 1))
    par = parent.labware

    # this needs to change to look up the current deck type if/when we add
    # that notion
    xforms_ser = definition['slotTransforms']\
        .get('ot2_standard', {})\
        .get(par, {'labwareOffset': [[1, 0, 0], [0, 1, 0], [0, 0, 1]]})
    xform_ser = xforms_ser['labwareOffset']

    # apply the slot transform if any
    xform = np.array(xform_ser)
    xformed = np.dot(xform, pre_transform)
    opts = {
        'parent': parent,
        'api_level': api_level,
        'offset': Point(xformed[0], xformed[1],
                        definition['labwareOffset']['z']),
        'overall_height': definition['dimensions']['bareOverallHeight'],
        'height_over_labware': definition['dimensions']['overLabwareHeight'],
        'model': module_model_from_string(definition['model']),
        'module_type': ModuleType.from_str(definition['moduleType']),
        'display_name': definition['displayName']
    }
    if definition['moduleType'] in {
            ModuleType.MAGNETIC.value, ModuleType.TEMPERATURE.value
    }:
        return ModuleGeometry(**opts)
    elif definition['moduleType'] == ModuleType.THERMOCYCLER.value:
        return ThermocyclerGeometry(
            lid_height=definition['dimensions']['lidHeight'],
            configuration=configuration,
            **opts)
    else:
        raise RuntimeError(f'Unknown module type {definition["moduleType"]}')
Example #12
0
    def remove_supernatant(vol, park=False):
        def waste_track(vol):
            nonlocal waste_vol
            if waste_vol + vol >= waste_threshold:
                # Setup for flashing lights notification to empty liquid waste
                # if not ctx._hw_manager.hardware.is_simulator:
                #     cancellationToken.set_true()
                # thread = create_thread(ctx, cancellationToken)
                m300.home()
                ctx.pause(
                    'Please empty liquid waste (slot 11) before resuming.')

                ctx.home()  # home before continuing with protocol
                # cancellationToken.set_false() # stop light flashing after home
                # thread.join()
                waste_vol = 0
            waste_vol += vol

        m300.flow_rate.aspirate = 30
        num_trans = math.ceil(vol / 200)
        vol_per_trans = vol / num_trans
        for m, spot in zip(mag_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))
            for _ in range(num_trans):
                waste_track(vol_per_trans)
                if m300.current_volume > 0:
                    m300.dispense(m300.current_volume,
                                  m.top())  # void air gap if necessary
                m300.move_to(m.center())
                m300.transfer(vol_per_trans,
                              loc,
                              waste,
                              new_tip='never',
                              air_gap=20)
                m300.blow_out(waste)
                m300.air_gap(20)
            drop(m300)
        m300.flow_rate.aspirate = 150
Example #13
0
    def wash(vol, source, mix_reps=15, park=True, resuspend=True):

        if resuspend and magdeck.status == 'engaged':
            magdeck.disengage()

        num_trans = math.ceil(vol / 200)
        vol_per_trans = vol / num_trans
        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))
            src = source[i // (12 // len(source))]
            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)
            if park:
                m300.drop_tip(spot)
            else:
                _drop(m300)
        ctx.pause('Mix on bioshake to resuspend')
        device.exec_cmd('setShakeTargetSpeed800')
        device.exec_cmd('shakeOn')
        ctx.delay(minutes=3)
        device.exec_cmd('shakeOff')
        ctx.pause('Mix off deck to resuspend pellet')
        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, park=park)
Example #14
0
 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:
         pip.home()
         ctx.set_rail_lights(True)
         ctx.pause('Please empty tips from waste before resuming.')
         ctx.set_rail_lights(False)
         ctx.home()  # home before continuing with protocol
         drop_count = 0
     return drop_loc
Example #15
0
    def __init__(self, well_props: 'WellDefinition', parent: Location,
                 display_name: str, has_tip: bool,
                 api_level: APIVersion) -> 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']
Example #16
0
 def drop(pip, loc=None):
     nonlocal switch
     nonlocal drop_count
     if not loc:
         if pip.type == 'multi':
             drop_count += 8
         else:
             drop_count += 1
         if drop_count >= drop_threshold:
             ctx.home()
             ctx.pause('Please empty tips from waste before resuming.')
             drop_count = 0
         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
     else:
         pip.drop_tip(loc)
    def wash_blot():
        for wash, blot in zip(pin_wash_res.wells(), blot_res.wells()):
            movement_locs = [
                wash.center().move(Point(x=side * 5)) for side in [-1, 1]
            ]
            m300.move_to(wash.center())
            for _ in range(5):
                for m in movement_locs:
                    m300.move_to(m)
            m300.move_to(wash.center())

            ctx.max_speeds['A'] = slow_speed
            ctx.max_speeds['Z'] = slow_speed
            m300.move_to(blot.top())
            m300.move_to(blot.bottom())
            ctx.delay(seconds=blot_dwell_time)

            del ctx.max_speeds['A']
            del ctx.max_speeds['Z']
    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:
            # Setup for flashing lights notification to empty trash
            if not ctx._hw_manager.hardware.is_simulator:
                cancellationToken.set_true()
            thread = create_thread(ctx, cancellationToken)
            ctx.pause('Please empty tips from waste before resuming.')

            ctx.home()  # home before continuing with protocol
            cancellationToken.set_false()  # stop light flashing after home
            thread.join()
            drop_count = 0
    def remove_supernatant(vol, pip=m300, park=False, direct=True):
        """
        `remove_supernatant` will transfer supernatant from the deepwell
        extraction plate to the liquid waste reservoir.
        :param vol (float): The amount of volume to aspirate from all deepwell
                            sample wells and dispense in the liquid waste.
        :param park (boolean): Whether to pick up sample-corresponding tips
                               in the 'parking rack' or to pick up new tips.
        """
        def _waste_track(vol):
            nonlocal waste_vol
            if waste_vol + vol >= waste_threshold:
                # Setup for flashing lights notification to empty liquid waste
                ctx.home()
                waste_vol = 0
            waste_vol += vol

        for i, (m, spot) in enumerate(zip(mag_samples_m, parking_spots)):
            if park:
                _pick_up(pip, spot)
            else:
                _pick_up(pip)
            side = -1 if i % 2 == 0 else 1
            loc = m.bottom(0).move(
                Point(x=side * radius * radial_offset, z=z_offset))
            _waste_track(vol)
            pip.move_to(m.center())
            # if pip == m300:
            #     air_gap_vol = 20
            # else:
            #     air_gap_vol = pip.max_volume - vol
            if direct and vol + \
                    air_gap_vol <= pip.tip_racks[0].wells()[0].max_volume:
                pip.aspirate(vol, loc)
                _drop(pip)
            else:
                pip.transfer(vol,
                             loc,
                             waste,
                             new_tip='never',
                             air_gap=air_gap_vol)
                pip.blow_out(waste)
                _drop(pip)
Example #20
0
def test_module_load_labware():
    module_names = ['tempdeck', 'magdeck']
    labware_name = 'corning_96_wellplate_360ul_flat'
    labware_def = labware.get_labware_definition(labware_name)
    for name in module_names:
        mod = labware.load_module(name, Location(Point(0, 0, 0), 'test'))
        old_z = mod.highest_z
        lw = labware.load_from_definition(labware_def, mod.location)
        mod.add_labware(lw)
        assert mod.labware == lw
        assert mod.highest_z ==\
            (mod.location.point.z
             + labware_def['dimensions']['zDimension']
             + mod._over_labware)
        with pytest.raises(AssertionError):
            mod.add_labware(lw)
        mod.reset_labware()
        assert mod.labware is None
        assert mod.highest_z == old_z
    def wash(vol, source, mix_reps=15, park=True, resuspend=True):

        global whichwash #Defines which wash the protocol is on to log on the app

        if source == wash1:
            whichwash = 1
        if source == wash2:
            whichwash = 2

        if resuspend and magdeck.status == 'engaged':
            magdeck.disengage()

        num_trans = math.ceil(vol/200)
        vol_per_trans = vol/num_trans
        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))
            src = source[i//(12//len(source))]
            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:
                resuspend_pellet(m, m300, 180)

            m300.blow_out(m.top())
            m300.air_gap(20)
            if park:
                m300.drop_tip(spot)
            else:
                _drop(m300)

        if magdeck.status == 'disengaged':
            magdeck.engage(height=MAG_HEIGHT)

        for washi in np.arange(settling_time,0,-0.5): #settling time timer for washes
            ctx.delay(minutes=0.5, msg='There are ' + str(washi) + ' minutes left in wash ' + str(whichwash) + ' incubation.')

        remove_supernatant(vol, park=park)
Example #22
0
def _load_from_v1(definition: 'ModuleDefinitionV1', parent: Location,
                  api_level: APIVersion) -> ModuleGeometry:
    """ Load a module geometry from a v1 definition.

    The definition should be schema checked before being passed to this
    function; all definitions passed here are assumed to be valid.
    """
    mod_name = definition['loadName']
    model_lookup: Mapping[str, ModuleModel] = {
        'thermocycler': ThermocyclerModuleModel.THERMOCYCLER_V1,
        'magdeck': MagneticModuleModel.MAGNETIC_V1,
        'tempdeck': TemperatureModuleModel.TEMPERATURE_V1
    }
    type_lookup = {
        'thermocycler': ModuleType.THERMOCYCLER,
        'tempdeck': ModuleType.TEMPERATURE,
        'magdeck': ModuleType.MAGNETIC
    }
    model = model_lookup[mod_name]
    offset = Point(definition["labwareOffset"]["x"],
                   definition["labwareOffset"]["y"],
                   definition["labwareOffset"]["z"])
    overall_height = definition["dimensions"]["bareOverallHeight"]\

    height_over_labware = definition["dimensions"]["overLabwareHeight"]

    if model in ThermocyclerModuleModel:
        lid_height = definition['dimensions']['lidHeight']
        mod: ModuleGeometry = \
            ThermocyclerGeometry(definition["displayName"],
                                 model,
                                 type_lookup[mod_name],
                                 offset,
                                 overall_height,
                                 height_over_labware,
                                 lid_height,
                                 parent,
                                 api_level)
    else:
        mod = ModuleGeometry(definition['displayName'], model,
                             type_lookup[mod_name], offset, overall_height,
                             height_over_labware, parent, api_level)
    return mod
Example #23
0
    async def _return_tip(self):
        """
        Move pipette with tip to tip rack well, such that
        the tip is inside the well, but not so deep that
        the tip rack will block the sheath from ejecting fully.
        Each pipette config contains a coefficient to apply to an
        attached tip's length to determine proper z offset
        """
        if self._tip_origin_pt and self._hw_pipette.has_tip:
            tip_length = self._get_default_tip_length()
            coeff = self._hw_pipette.config.return_tip_height
            to_pt = self._tip_origin_pt - Point(0, 0, tip_length * coeff)

            cp = self._get_critical_point()
            await self._hardware.move_to(mount=self._mount,
                                         abs_position=to_pt,
                                         critical_point=cp)
            await self._hardware.drop_tip(self._mount)
            self._tip_origin_pt = None
 def remove_supernatant(vol):
     m300.flow_rate.aspirate = 30
     num_trans = math.ceil(vol / 270)
     vol_per_trans = vol / num_trans
     for i, m in enumerate(mag_samples_m):
         side = -1 if i < 6 == 0 else 1
         loc = m.bottom(0.5).move(Point(x=side * 2))
         if not m300.hw_pipette['has_tip']:
             pick_up(m300)
         for _ in range(num_trans):
             m300.move_to(m.center())
             m300.transfer(vol_per_trans,
                           loc,
                           waste,
                           new_tip='never',
                           air_gap=30)
             m300.blow_out(waste)
         m300.drop_tip()
     m300.flow_rate.aspirate = 150
Example #25
0
    def remove_supernatant():
        nonlocal waste_vol_ctr
        nonlocal waste_well_ctr

        ctx.comment('\n\n\nREMOVING SUPERNATANT\n')
        for i, col in enumerate(sample_cols):
            side = -1 if i % 2 == 0 else 1
            aspirate_loc = col.bottom(1).move(
                    Point(x=(col.length/2-2)*side))
            pick_up()
            for _ in range(2):
                m300.aspirate(200 if filter_tips else 300, aspirate_loc, rate=0.6)  # noqa E501
                m300.dispense(200 if filter_tips else 300, waste_res.wells()[waste_well_ctr])    # noqa E501
                m300.blow_out(waste_res.wells()[waste_well_ctr].top())
                waste_vol_ctr += 200
                if waste_vol_ctr >= 12000:
                    waste_vol_ctr = 0
                    waste_well_ctr += 1
            m300.drop_tip()
Example #26
0
    def critical_point(self, cp_override: CriticalPoint = None) -> Point:
        """
        The vector from the pipette's origin to its critical point. The
        critical point for a pipette is the end of the nozzle if no tip is
        attached, or the end of the tip if a tip is attached.

        If `cp_override` is specified and valid - so is either
        :py:attr:`CriticalPoint.NOZZLE` or :py:attr:`CriticalPoint.TIP` when
        we have a tip, or :py:attr:`CriticalPoint.XY_CENTER` - the specified
        critical point will be used.
        """
        if not self.has_tip or cp_override == CriticalPoint.NOZZLE:
            cp_type = CriticalPoint.NOZZLE
            tip_length = 0.0
        else:
            cp_type = CriticalPoint.TIP
            tip_length = self.current_tip_length
        if cp_override == CriticalPoint.XY_CENTER:
            mod_offset_xy = [0, 0, self.model_offset[2]]
            cp_type = CriticalPoint.XY_CENTER
        elif cp_override == CriticalPoint.FRONT_NOZZLE:
            mod_offset_xy = [0, -self.model_offset[1], self.model_offset[2]]
            cp_type = CriticalPoint.FRONT_NOZZLE
        else:
            mod_offset_xy = self.model_offset
        mod_and_tip = Point(mod_offset_xy[0], mod_offset_xy[1],
                            mod_offset_xy[2] - tip_length)
        cp = mod_and_tip + self._instrument_offset._replace(z=0)
        if self._log.isEnabledFor(logging.DEBUG):
            mo = 'model offset: {} + '.format(self.model_offset)\
                if cp_type != CriticalPoint.XY_CENTER else ''
            info_str = 'cp: {}{}: {}=({}instr offset xy: {}'\
                .format(cp_type, '(from override)' if cp_override else '',
                        cp, mo,
                        self._instrument_offset._replace(z=0))
            if cp_type == CriticalPoint.TIP:
                info_str += '- current_tip_length: {}=(true tip length: {}'\
                    ' - inst z: {}) (z only)'.format(
                        self.current_tip_length, self._current_tip_length,
                        self._instrument_offset.z)
            info_str += ')'
            self._log.debug(info_str)
        return cp
Example #27
0
def test_touch_tip_new_default_args(loop, monkeypatch):
    ctx = papi.ProtocolContext(loop)
    ctx.home()
    lw = ctx.load_labware(
        'opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap', 1)
    tiprack = ctx.load_labware('opentrons_96_tiprack_300ul', 3)
    instr = ctx.load_instrument('p300_single',
                                Mount.RIGHT,
                                tip_racks=[tiprack])

    instr.pick_up_tip()
    total_hw_moves = []

    async def fake_hw_move(self,
                           mount,
                           abs_position,
                           speed=None,
                           critical_point=None,
                           max_speeds=None):
        nonlocal total_hw_moves
        total_hw_moves.append((abs_position, speed))

    instr.aspirate(10, lw.wells()[0])
    monkeypatch.setattr(API, 'move_to', fake_hw_move)
    instr.touch_tip()
    z_offset = Point(0, 0, 1)  # default z offset of 1mm
    speed = 60  # default speed
    edges = [
        lw.wells()[0]._from_center_cartesian(1, 0, 1) - z_offset,
        lw.wells()[0]._from_center_cartesian(-1, 0, 1) - z_offset,
        lw.wells()[0]._from_center_cartesian(0, 0, 1) - z_offset,
        lw.wells()[0]._from_center_cartesian(0, 1, 1) - z_offset,
        lw.wells()[0]._from_center_cartesian(0, -1, 1) - z_offset
    ]
    for i in range(1, 5):
        assert total_hw_moves[i] == (edges[i - 1], speed)

    # Check that the new api version initial well move has the same z height
    # as the calculated edges.
    total_hw_moves.clear()
    instr.touch_tip(v_offset=1)
    assert total_hw_moves[0][0].z == total_hw_moves[1][0].z
async def test_tip_probe_v2(main_router, model, monkeypatch):

    def fake_update(mount, new_offset=None, from_tip_probe=None):
        assert mount == Mount[model.instrument.mount.upper()]
        if new_offset:
            assert new_offset == Point(0, 0, 0)
        elif from_tip_probe:
            assert from_tip_probe == Point(0, 0, 0)
        else:
            assert False, "fake_update called with no args"

    def fake_move(instrument):
        assert instrument == model.instrument

    monkeypatch.setattr(main_router.calibration_manager._hardware._api,
                        'update_instrument_offset', fake_update)
    monkeypatch.setattr(main_router.calibration_manager,
                        'move_to_front', fake_move)

    tr = labware.load('opentrons_96_tiprack_300ul', Location(Point(), 'test'))

    model.instrument.tip_racks = [
        models.Container(tr,
                         [model.instrument._instrument],
                         model.instrument._context)]

    def new_fake_locate(mount, tip_length):
        assert tip_length == pytest.approx(59.3-7.47)
        return Point(0, 0, 0)

    monkeypatch.setattr(main_router.calibration_manager._hardware._api,
                        'locate_tip_probe_center', new_fake_locate)
    main_router.calibration_manager.tip_probe(model.instrument)
    await main_router.wait_until(state('ready'))

    def new_fake_locate2(mount, tip_length):
        assert tip_length == pytest.approx(59.3-7.47)
        return Point(0, 0, 0)

    monkeypatch.setattr(main_router.calibration_manager._hardware._api,
                        'locate_tip_probe_center', new_fake_locate2)
    main_router.calibration_manager.tip_probe(model.instrument)
Example #29
0
    def get_comparisons_by_step(
            self) -> typing.Dict[CalibrationCheckState, ComparisonStatus]:
        comparisons = {}
        for jogged_state, comp in COMPARISON_STATE_MAP.items():
            ref_pt = self._saved_points.get(getattr(CalibrationCheckState,
                                                    comp.reference_state),
                                            None)
            jogged_pt = self._saved_points.get(getattr(CalibrationCheckState,
                                                       jogged_state), None)
            if (ref_pt is not None and jogged_pt is not None):
                diff_magnitude = None
                if comp.threshold_vector.z == 0.0:
                    diff_magnitude = ref_pt._replace(z=0.0).magnitude_to(
                            jogged_pt._replace(z=0.0))
                elif comp.threshold_vector.x == 0.0 and \
                        comp.threshold_vector.y == 0.0:
                    diff_magnitude = ref_pt._replace(
                            x=0.0, y=0.0).magnitude_to(jogged_pt._replace(
                                                       x=0.0, y=0.0))
                assert diff_magnitude is not None, \
                    'step comparisons must check z or (x and y) magnitude'

                threshold_mag = Point(0, 0, 0).magnitude_to(
                        comp.threshold_vector)
                exceeds = diff_magnitude > threshold_mag
                tform_type = DeckCalibrationError.UNKNOWN

                if exceeds:
                    is_second_pip = jogged_state in [
                        CalibrationCheckState.joggingSecondPipetteToHeight,
                        CalibrationCheckState.joggingSecondPipetteToPointOne,
                    ]
                    if is_second_pip:
                        tform_type = DeckCalibrationError.BAD_INSTRUMENT_OFFSET
                    elif self.can_distinguish_instr_offset():
                        tform_type = DeckCalibrationError.BAD_DECK_TRANSFORM
                comparisons[getattr(CalibrationCheckState, jogged_state)] = \
                    ComparisonStatus(differenceVector=(jogged_pt - ref_pt),
                                     thresholdVector=comp.threshold_vector,
                                     exceedsThreshold=exceeds,
                                     transformType=tform_type)
        return comparisons
Example #30
0
def test_module_load_labware(loop):
    ctx = papi.ProtocolContext(loop)
    labware_name = 'corning_96_wellplate_360ul_flat'
    # TODO Ian 2019-05-29 load fixtures, not real defs
    labware_def = json.loads(
        load_shared_data(f'labware/definitions/2/{labware_name}/1.json'))
    ctx._hw_manager.hardware._backend._attached_modules = [('mod0', 'tempdeck')
                                                           ]
    mod = ctx.load_module('Temperature Module', 1)
    assert mod.labware is None
    lw = mod.load_labware(labware_name)
    lw_offset = Point(labware_def['cornerOffsetFromSlot']['x'],
                      labware_def['cornerOffsetFromSlot']['y'],
                      labware_def['cornerOffsetFromSlot']['z'])
    assert lw._offset == lw_offset + mod._geometry.location.point
    assert lw.name == labware_name
    # Test load with old name
    mod2 = ctx.load_module('tempdeck', 2)
    lw2 = mod2.load_labware(labware_name)
    assert lw2._offset == lw_offset + mod2._geometry.location.point