def run(protocol: protocol_api.ProtocolContext(api_version=api_version)):

    # define deck positions and labware

    # tips
    tiprack_300 = protocol.load_labware('opentrons_96_tiprack_300ul', 6)

    tipracks_10f = [
        protocol.load_labware('opentrons_96_filtertiprack_10ul', x)
        for x in [1, 4, 7, 10]
    ]

    # plates
    reagents = protocol.load_labware('usascientific_12_reservoir_22ml', 3,
                                     'reagents')
    assay = protocol.load_labware('corning_384_wellplate_112ul_flat', 9,
                                  'assay')

    samples = [
        protocol.load_labware('biorad_96_wellplate_200ul_pcr', x, 'samples')
        for x in [2, 5, 8, 11]
    ]

    # initialize pipettes
    pipette_left = protocol.load_instrument('p300_multi',
                                            'left',
                                            tip_racks=[tiprack_300])

    pipette_right = protocol.load_instrument('p10_multi',
                                             'right',
                                             tip_racks=tipracks_10f)

    # distribute 38 µL of quantification reagent into each well of the assay
    # plate. Use the same tip for the entirety of these transfers, then
    # replace it in the rack.

    add_buffer(pipette_left, [reagents[x] for x in ['A1', 'A2']],
               assay,
               cols,
               38,
               13000 / 8,
               tip=None,
               tip_vol=300,
               remaining=None,
               drop_tip=False)

    # add 2 µL of each sample to each of the wells. Mix after dispensing.
    # Dispose of these tips.
    for i, plate in enumerate(samples):
        start = i + 1
        assay_wells = get_96_from_384_wells(method='interleaved', start=start)
        pipette_right.transfer(2,
                               plate.wells(), [assay[x] for x in assay_wells],
                               mix_after=(1, 10),
                               touch_tip=True,
                               trash=True,
                               new_tip='always')
Пример #2
0
def run(protocol: protocol_api.ProtocolContext):

    # define deck positions and labware

    # tips
    tiprack_300 = protocol.load_labware('opentrons_96_tiprack_300ul', 1)
    tiprack_10f = protocol.load_labware('opentrons_96_filtertiprack_10ul', 2)

    # plates
    reagents = protocol.load_labware('usascientific_12_reservoir_22ml',
                                     6, 'reagents')
    assay = protocol.load_labware('corning_96_wellplate_360ul_flat',
                                  5, 'assay')
    samples = protocol.load_labware('biorad_96_wellplate_200ul_pcr',
                                    4, 'samples')

    # initialize pipettes
    pipette_left = protocol.load_instrument('p300_multi',
                                            'left',
                                            tip_racks=[tiprack_300])

    pipette_right = protocol.load_instrument('p10_multi',
                                             'right',
                                             tip_racks=[tiprack_10f])

    # # home instrument
    # protocol.home()

    # distribute 198 µL of quantification reagent into each well of the assay
    # plate. Use the same tip for the entirety of these transfers, then
    # replace it in the rack.

    add_buffer(pipette_left,
               [reagents[x] for x in ['A1', 'A2']],
               assay,
               cols,
               198,
               13000/8,
               tip=None,
               tip_vol=300,
               remaining=None,
               drop_tip=False)

    # add 2 µL of each sample to each of the wells. Mix after dispensing.
    # Dispose of these tips.
    pipette_right.transfer(2,
                           [samples[x] for x in cols],
                           [assay[x] for x in cols],
                           mix_after=(5, 10),
                           touch_tip=True,
                           trash=False,
                           new_tip='always')
Пример #3
0
def test_add_buffer_fullplate():
    protocol = get_protocol_api(apilevel)

    tips = protocol.load_labware('opentrons_96_tiprack_300ul', 8)
    plate = protocol.load_labware('biorad_96_wellplate_200ul_pcr',
                                  3, 'plate')
    reagents = protocol.load_labware('usascientific_12_reservoir_22ml',
                                     9, 'reagents')
    pipette = protocol.load_instrument('p300_multi',
                                       'left',
                                       tip_racks=[tips])

    remaining, source_wells = add_buffer(pipette,
                                         [reagents['A1'],
                                          reagents['A2']],
                                         plate,
                                         ['A1', 'A2', 'A3', 'A4',
                                          'A5', 'A6', 'A7', 'A8',
                                          'A9', 'A10', 'A11', 'A12'],
                                         300,
                                         20000 / 8,
                                         dead_vol=800 / 8)

    assert remaining == 1300
    assert source_wells == [reagents['A2']]
Пример #4
0
def test_add_buffer():
    protocol = get_protocol_api(apilevel)
    scraper = CommandScraper(logging.getLogger('opentrons'),
                             '1',
                             protocol.broker)

    tips = protocol.load_labware('opentrons_96_tiprack_300ul', 8)
    plate = protocol.load_labware('biorad_96_wellplate_200ul_pcr',
                                  3, 'plate')
    reagents = protocol.load_labware('nest_12_reservoir_15ml',
                                     9, 'reagents')
    pipette = protocol.load_instrument('p300_multi',
                                       'left',
                                       tip_racks=[tips])

    remaining, source_wells = add_buffer(pipette,
                                         [reagents['A1']],
                                         plate,
                                         ['A1', 'A2'],
                                         300,
                                         1000)

    assert remaining == 400
    assert source_wells == [reagents['A1']]

    exp = ['Picking up tip from A1 of Opentrons 96 Tip Rack 300 µL on 8',
           'Aspirating 150.0 uL from A1 of reagents on 9 at 1.0 speed',
           'Air gap',
           'Aspirating 10.0 uL from A1 of reagents on 9 at 1.0 speed',
           'Dispensing 160.0 uL into A1 of plate on 3 at 1.0 speed',
           'Aspirating 150.0 uL from A1 of reagents on 9 at 1.0 speed',
           'Air gap',
           'Aspirating 10.0 uL from A1 of reagents on 9 at 1.0 speed',
           'Dispensing 160.0 uL into A1 of plate on 3 at 1.0 speed',
           'Blowing out',
           'Aspirating 150.0 uL from A1 of reagents on 9 at 1.0 speed',
           'Air gap',
           'Aspirating 10.0 uL from A1 of reagents on 9 at 1.0 speed',
           'Dispensing 160.0 uL into A2 of plate on 3 at 1.0 speed',
           'Aspirating 150.0 uL from A1 of reagents on 9 at 1.0 speed',
           'Air gap',
           'Aspirating 10.0 uL from A1 of reagents on 9 at 1.0 speed',
           'Dispensing 160.0 uL into A2 of plate on 3 at 1.0 speed',
           'Blowing out',
           'Dropping tip into A1 of Opentrons Fixed Trash on 12']

    obs = [x['payload']['text'] for x in scraper.commands]

    assert exp == obs
Пример #5
0
def test_add_buffer_runout():
    protocol = get_protocol_api(apilevel)

    tips = protocol.load_labware('opentrons_96_tiprack_300ul', 8)
    plate = protocol.load_labware('biorad_96_wellplate_200ul_pcr',
                                  3, 'plate')
    reagents = protocol.load_labware('nest_12_reservoir_15ml',
                                     9, 'reagents')
    pipette = protocol.load_instrument('p300_multi',
                                       'left',
                                       tip_racks=[tips])

    with pytest.raises(IndexError):
        remaining, source_wells = add_buffer(pipette,
                                             [reagents['A1']],
                                             plate,
                                             ['A1', 'A2'],
                                             300,
                                             600)
Пример #6
0
def run(protocol: protocol_api.ProtocolContext):

    # ### Setup

    # define deck positions and labware

    # define hardware modules
    magblock = protocol.load_module('Magnetic Module', 10)
    magblock.disengage()

    # tips
    tiprack_buffers = protocol.load_labware('opentrons_96_tiprack_300ul', 8)
    tiprack_elution_1 = protocol.load_labware(
        'opentrons_96_filtertiprack_200ul', 5)
    tiprack_elution_2 = protocol.load_labware(
        'opentrons_96_filtertiprack_200ul', 6)
    tiprack_wash = protocol.load_labware('opentrons_96_tiprack_300ul', 4)

    # plates
    wash_buffers = protocol.load_labware('usascientific_12_reservoir_22ml', 11,
                                         'wash buffers')
    eluate = protocol.load_labware('biorad_96_wellplate_200ul_pcr', 3,
                                   'eluate')
    waste = protocol.load_labware('nest_1_reservoir_195ml', 7, 'liquid waste')
    reagents = protocol.load_labware('usascientific_12_reservoir_22ml', 9,
                                     'reagents')

    # load plate on magdeck
    # mag_plate = magblock.load_labware('vwr_96_wellplate_1000ul')
    mag_plate = magblock.load_labware('vwr_96_wellplate_1000ul')

    # initialize pipettes
    pipette_left = protocol.load_instrument('p300_multi',
                                            'left',
                                            tip_racks=[tiprack_buffers])

    # MagBindingBuffer + beads wells
    mbb_wells = [reagents[x] for x in mbb_cols]

    # MagBindingBuffer wells
    mbw_wells = [reagents[x] for x in mbw_cols]

    # Wash 1 columns
    w1_wells = [wash_buffers[x] for x in w1_cols]

    # Wash 2 columns
    w2_wells = [wash_buffers[x] for x in w2_cols]

    # ### Prompt user to place plate on mag block
    protocol.pause('Add plate containing 200 µL per well of lysis supernatant'
                   ' onto the magdeck in position 10.')

    # ### Add MagBinding buffer and beads to plate
    protocol.comment('Adding beads to plate.')

    # add beads
    mbb_remaining, mbb_wells = add_buffer(pipette_left,
                                          mbb_wells,
                                          mag_plate,
                                          cols,
                                          625,
                                          18000 / 8,
                                          pre_mix=10)

    # mix beads and samples
    for col in cols:
        pipette_left.pick_up_tip(tiprack_wash.wells_by_name()[col])
        pipette_left.mix(10, 250, mag_plate[col].bottom(z=1))
        pipette_left.blow_out(mag_plate[col].top(z=-2))
        pipette_left.touch_tip()
        pipette_left.return_tip()

    # bind to beads
    protocol.comment('Binding DNA to beads.')
    protocol.delay(seconds=pause_bind)

    # mix again
    for col in cols:
        pipette_left.pick_up_tip(tiprack_wash.wells_by_name()[col])
        pipette_left.mix(10, 250, mag_plate[col].bottom(z=1))
        pipette_left.blow_out(mag_plate[col].top(z=-2))
        pipette_left.touch_tip()
        pipette_left.return_tip()

    # bind to magnet
    protocol.comment('Binding beads to magnet.')
    magblock.engage(height_from_base=mag_engage_height)

    protocol.delay(seconds=pause_mag)

    # ### Do first wash: Wash 500 µL MagBinding buffer
    protocol.comment('Doing wash #1.')
    mbw_remaining, mbw_wells = bead_wash(
        # global arguments
        protocol,
        magblock,
        pipette_left,
        mag_plate,
        cols,
        # super arguments
        waste['A1'],
        tiprack_wash,
        # wash buffer arguments,
        mbw_wells,
        19000 / 8,
        # mix arguments
        tiprack_wash,
        # optional arguments
        wash_vol=500,
        super_vol=800,
        drop_super_tip=False,
        mix_n=wash_mix,
        mag_engage_height=mag_engage_height)

    # ### Do second wash: Wash 500 µL MagWash 1
    protocol.comment('Doing wash #2.')
    w1_remaining, w1_wells = bead_wash(
        # global arguments
        protocol,
        magblock,
        pipette_left,
        mag_plate,
        cols,
        # super arguments
        waste['A1'],
        tiprack_wash,
        # wash buffer arguments
        w1_wells,
        19000 / 8,
        # mix arguments
        tiprack_wash,
        # optional arguments,
        wash_vol=500,
        super_vol=500,
        drop_super_tip=False,
        mix_n=wash_mix,
        remaining=None,
        mag_engage_height=mag_engage_height)

    # ### Do third wash: Wash 900 µL MagWash 2
    protocol.comment('Doing wash #3.')
    w2_remaining, w2_wells = bead_wash(
        # global arguments
        protocol,
        magblock,
        pipette_left,
        mag_plate,
        cols,
        # super arguments
        waste['A1'],
        tiprack_wash,
        # wash buffer arguments
        w2_wells,
        21000 / 8,
        # mix arguments
        tiprack_wash,
        # optional arguments,
        wash_vol=900,
        super_vol=500,
        drop_super_tip=False,
        mix_n=wash_mix,
        remaining=None,
        mag_engage_height=mag_engage_height)

    # ### Do fourth wash: Wash 900 µL MagWash 2
    protocol.comment('Doing wash #4.')
    w2_remaining, w2_wells = bead_wash(
        # global arguments
        protocol,
        magblock,
        pipette_left,
        mag_plate,
        cols,
        # super arguments
        waste['A1'],
        tiprack_wash,
        # wash buffer arguments
        w2_wells,
        21000 / 8,
        # mix arguments
        tiprack_wash,
        # optional arguments,
        wash_vol=900,
        super_vol=900,
        drop_super_tip=False,
        mix_n=wash_mix,
        remaining=w2_remaining,
        mag_engage_height=mag_engage_height)

    # ### Dry
    protocol.comment('Removing wash and drying beads.')

    # This should:
    # - pick up tip in position 8
    # - pick up supernatant from magplate
    # - dispense in waste, position 11
    # - repeat
    # - trash tip
    # - leave magnet engaged

    # remove supernatant
    remove_supernatant(pipette_left,
                       mag_plate,
                       cols,
                       tiprack_wash,
                       waste['A1'],
                       super_vol=1000,
                       rate=bead_flow,
                       bottom_offset=.5,
                       drop_tip=True)

    # dry
    protocol.delay(seconds=pause_dry)

    # ### Elute
    protocol.comment('Eluting DNA from beads.')

    # This should:
    # - disengage magnet
    # - pick up tip from position 6
    # - pick up reagents from column 2 of position 9
    # - dispense into magplate
    # - mix 10 times
    # - blow out, touch tip
    # - return tip to position 6
    # - wait (5 seconds)
    # - engage magnet
    # - wait (5 seconds)
    # - pick up tip from position 6
    # - aspirate from magplate
    # - dispense to position 3
    # - trash tip

    # transfer elution buffer to mag plate
    magblock.disengage()

    # add elution buffer and mix
    for col in cols:
        pipette_left.pick_up_tip(tiprack_elution_1.wells_by_name()[col])
        pipette_left.aspirate(50, reagents['A8'], rate=1)
        pipette_left.dispense(50, mag_plate[col].bottom(z=1))
        pipette_left.mix(10, 40, mag_plate[col].bottom(z=1))
        pipette_left.blow_out(mag_plate[col].top())
        pipette_left.touch_tip()
        # we'll use these same tips for final transfer
        pipette_left.return_tip()

    protocol.delay(seconds=pause_elute)
    # # start timer
    # t0 = clock()
    # # mix again
    # t_mix = 0
    # while t_mix < pause_elute():
    for col in cols:
        pipette_left.pick_up_tip(tiprack_elution_1.wells_by_name()[col])
        pipette_left.mix(10, 40, mag_plate[col].bottom(z=1))
        pipette_left.blow_out(mag_plate[col].top())
        pipette_left.touch_tip()
        # we'll use these same tips for final transfer
        pipette_left.return_tip()
        # t_mix = clock() - t0

    # bind to magnet
    protocol.comment('Binding beads to magnet.')

    magblock.engage(height_from_base=mag_engage_height)

    protocol.delay(seconds=pause_mag)

    protocol.comment('Transferring eluted DNA to final plate.')
    for col in cols:
        pipette_left.pick_up_tip(tiprack_elution_2.wells_by_name()[col])
        pipette_left.aspirate(50, mag_plate[col].bottom(z=2), rate=bead_flow)
        pipette_left.dispense(50, eluate[col])
        pipette_left.blow_out(eluate[col].top())
        pipette_left.touch_tip()
        # we're done with these tips now
        pipette_left.drop_tip()

    magblock.disengage()
Пример #7
0
def bead_wash(  # global arguments
              protocol,
              magblock,
              pipette,
              plate,
              cols,
              # super arguments
              super_waste,
              super_tiprack,
              # wash buffer arguments
              source_wells,
              source_vol,
              # mix arguments
              mix_tiprack,
              # optional arguments
              super_vol=600,
              rate=0.25,
              super_bottom_offset=2,
              super_tip_vol=200,
              drop_super_tip=True,
              wash_vol=300,
              remaining=None,
              wash_tip=None,
              wash_tip_vol=300,
              drop_wash_tip=True,
              mix_vol=200,
              mix_n=10,
              drop_mix_tip=False,
              mag_engage_height=None,
              pause_s=300):
    # Wash

    # This should:
    # - pick up tip from position 7
    # - pick up 190 µL from the mag plate
    # - air gap
    # - dispense into position 11
    # - repeat x
    # - trash tip
    # - move to next column
    # - disengage magnet

    # remove supernatant
    remove_supernatant(pipette,
                       plate,
                       cols,
                       super_tiprack,
                       super_waste,
                       tip_vol=super_tip_vol,
                       super_vol=super_vol,
                       rate=rate,
                       bottom_offset=super_bottom_offset,
                       drop_tip=drop_super_tip)

    # disengage magnet
    magblock.disengage()

    # This should:
    # - Pick up tips from column 3 of location 2
    # - pick up isopropanol from position 5 column 3
    # - dispense to `cols` in mag plate
    # - pick up isopropanol from position 5 column 4
    # - dispense to `cols` in mag plate
    # - drop tips at end

    # add isopropanol
    wash_wells, wash_remaining = add_buffer(pipette,
                                            source_wells,
                                            plate,
                                            cols,
                                            wash_vol,
                                            source_vol,
                                            tip=wash_tip,
                                            tip_vol=wash_tip_vol,
                                            remaining=remaining,
                                            drop_tip=drop_wash_tip)

    # This should:
    # - grab a tip from position 8
    # - mix 5 times the corresponding well on mag plate
    # - blow out
    # - return tip
    # - do next col
    # - engage magnet

    # mix
    bead_mix(pipette,
             plate,
             cols,
             mix_tiprack,
             n=mix_n,
             mix_vol=mix_vol,
             drop_tip=drop_mix_tip)

    # engage magnet
    if mag_engage_height is not None:
        magblock.engage(height_from_base=mag_engage_height)
    else:
        magblock.engage()

    protocol.delay(seconds=pause_s)

    return(wash_wells, wash_remaining)
Пример #8
0
def run(protocol: protocol_api.ProtocolContext):

    # # Magnetic DNA extraction protocol

    # #### This follows the Bio-On-Magnetic_Beads protocol 7.1 for
    # genomic DNA extraction.
    #
    # Isolates should have been bead-beat in our strip tubes and spun down in
    # the plate centrifuge.
    #
    # Reagents needed:
    # - reservoir plate with 15 mL lysis buffer in columns 1-4
    # - reservoir plate with 15 mL Isopropanol in columns 5-8
    # - reservoir plate with 15 mL 80% EtOH in columns 9-12
    # - deep well plate with ≥300 µL beads in each well of column 1
    # - deep well plate with 1 mL elution buffer in each well of column 2

    # ### Deck

    # 1. deep well plate (empty)
    # 2. 300 µL tips - buffer transfer
    # 3. PCR plate (final samples)
    # 4. Lysate
    # 5. reservoir plate (wash buffers)
    # 6. 200 µL filter tips - final transfer
    # 7. 200 µL filter tips - lysate transfer
    # 8. 300 µL tips - bead washes
    # 9. empty
    # 10. deep well plate (reagents)
    # 11. mag module
    # 12. trash

    # ### Setup

    # define deck positions and labware

    # define hardware modules
    magblock = protocol.load_module('Magnetic Module', 10)
    magblock.disengage()

    # tips
    tiprack_buffers = protocol.load_labware('opentrons_96_tiprack_300ul', 8)
    tiprack_elution_1 = protocol.load_labware(
        'opentrons_96_filtertiprack_200ul', 5)
    tiprack_elution_2 = protocol.load_labware(
        'opentrons_96_filtertiprack_200ul', 6)
    tiprack_wash = protocol.load_labware('opentrons_96_tiprack_300ul', 4)

    # plates
    wash_buffers = protocol.load_labware('usascientific_12_reservoir_22ml', 11,
                                         'wash buffers')
    eluate = protocol.load_labware('biorad_96_wellplate_200ul_pcr', 3,
                                   'eluate')
    waste = protocol.load_labware('nest_1_reservoir_195ml', 7, 'liquid waste')
    reagents = protocol.load_labware('nest_12_reservoir_15ml', 9, 'reagents')
    lysate = protocol.load_labware('axygen_96_wellplate_1100ul', 1, 'lysate')

    # load plate on magdeck
    mag_plate = magblock.load_labware('vwr_96_wellplate_1000ul')

    # initialize pipettes
    pipette_left = protocol.load_instrument('p300_multi',
                                            'left',
                                            tip_racks=[tiprack_buffers])

    # Lysis buffer wells
    lys_wells = [wash_buffers[x] for x in lys_cols]

    # Isopropanol wells
    ipa_wells = [wash_buffers[x] for x in ipa_cols]

    # Ethanol columns
    eth_wells = [wash_buffers[x] for x in eth_cols]

    # ### Prompt user to place cells with beads loaded on position 4
    protocol.pause('Add lysis beads to strip tubes containing dry cell pellet'
                   ' and place on position 4 for addition of lysis buffer.')

    # ### Add lysis buffer
    add_buffer(pipette_left, lys_wells, lysate, cols, 580, 18000 / 8)

    # ### Prompt user to remove plate
    protocol.pause('Remove plate from position 4. \n\n'
                   'Cap tubes in tube plate and beadbeat for required time. '
                   'Then spin down, uncap, and return to position 4. \n\n'
                   'Press continue to start filling plate on mag deck during '
                   'this time. There will be another pause after plate is '
                   'filled to allow you to return strip tube plate to '
                   'position 4 before continuing.')

    # ### Add beads to new plate
    protocol.comment('Adding beads to wash plate.')

    # This should:
    # - pick up a tip from location 2
    # - pick up reagents from column 1 of location 9
    # - distribute 20 µL to each column from `cols` in location 1.
    # - trash tip

    pipette_left.pick_up_tip()

    # mix beads
    pipette_left.mix(10, 150, reagents.wells_by_name()['A1'].bottom(z=2))

    pipette_left.distribute(20,
                            reagents.wells_by_name()['A1'],
                            [mag_plate[x] for x in cols],
                            mix_before=(2, 20),
                            touch_tip=False,
                            disposal_volume=10,
                            trash=True,
                            new_tip='never')

    pipette_left.drop_tip()

    # ### Add isopropanol
    protocol.comment('Adding isopropanol to wash plate.')

    # This should:
    # - Pick up tips from column 2 of location 2
    # - pick up isopropanol from position 5 column 1
    # - dispense to `cols` in position 1
    # - pick up isopropanol from position 5 column 2
    # - dispense to `cols` in position 1
    # - return tip at end

    ipa_remaining, ipa_wells = add_buffer(pipette_left, ipa_wells, mag_plate,
                                          cols, 300, 18000 / 8)

    protocol.pause('Decap and return spun-down strip tube plate to position '
                   '4. \n\nPress continue when ready.')

    # ### Transfer lysate to new plate

    # # This should:
    # - pick up tips in position 7
    # - pick up 180 µL lysate from plate in position 4
    # - air gap
    # - dispense into corresponding well in position 1
    # - blow out and touch tip
    # - repeat
    # - return tip to position 7

    # this needs to be modified to position transfer aspirate
    # location accurately.

    protocol.comment('Transferring lysate to wash plate.')

    for col in cols:
        # do first transfer.
        pipette_left.pick_up_tip(tiprack_wash.wells_by_name()[col])
        pipette_left.aspirate(180,
                              lysate[col].bottom(z=min_height + 5),
                              rate=0.25)
        pipette_left.air_gap(10)
        pipette_left.dispense(190, mag_plate[col].top(z=-5))
        pipette_left.blow_out()
        pipette_left.touch_tip(v_offset=-1)

        # do second transfer.
        pipette_left.aspirate(180, lysate[col].bottom(z=min_height), rate=0.25)
        pipette_left.air_gap(10)
        pipette_left.dispense(190, mag_plate[col].top(z=-5))
        pipette_left.blow_out()
        pipette_left.touch_tip(v_offset=-1)
        pipette_left.mix(5, 250, mag_plate[col].bottom(z=1))
        pipette_left.blow_out(mag_plate[col].top(z=-2))
        pipette_left.return_tip()

    # bind
    protocol.comment('Binding DNA to beads.')
    protocol.delay(seconds=pause_bind)

    # mix
    for col in cols:
        pipette_left.pick_up_tip(tiprack_wash.wells_by_name()[col])
        pipette_left.mix(5, 250, mag_plate[col].bottom(z=1))
        pipette_left.blow_out(mag_plate[col].top(z=-2))
        pipette_left.touch_tip()
        pipette_left.return_tip()

    # bind for specified length of time
    protocol.comment('Binding beads to magnet.')
    magblock.engage(height_from_base=mag_engage_height)

    protocol.delay(seconds=pause_mag)

    # ### Do first wash
    protocol.comment('Doing wash #1.')
    ipa_remaining, ipa_wells = bead_wash(
        # global arguments
        protocol,
        magblock,
        pipette_left,
        mag_plate,
        cols,
        # super arguments
        waste['A1'],
        tiprack_wash,
        # wash buffer arguments
        ipa_wells,
        18000 / 8,
        # mix arguments
        tiprack_wash,
        # optional arguments
        super_vol=700,
        drop_super_tip=False,
        mix_n=wash_mix,
        mix_vol=250,
        remaining=ipa_remaining,
        mag_engage_height=mag_engage_height)

    # ### Do second wash
    protocol.comment('Doing wash #2.')
    eth_remaining, eth_wells = bead_wash(
        # global arguments
        protocol,
        magblock,
        pipette_left,
        mag_plate,
        cols,
        # super arguments
        waste['A1'],
        tiprack_wash,
        # wash buffer arguments
        eth_wells,
        18000 / 8,
        # mix arguments
        tiprack_wash,
        # optional arguments,
        super_vol=300,
        drop_super_tip=False,
        mix_n=wash_mix,
        mix_vol=250,
        remaining=None,
        mag_engage_height=mag_engage_height)

    # ### Do third wash
    protocol.comment('Doing wash #3.')
    eth_remaining, eth_wells = bead_wash(
        # global arguments
        protocol,
        magblock,
        pipette_left,
        mag_plate,
        cols,
        # super arguments
        waste['A1'],
        tiprack_wash,
        # wash buffer arguments
        eth_wells,
        18000 / 8,
        # mix arguments
        tiprack_wash,
        # optional arguments,
        super_vol=300,
        drop_super_tip=False,
        mix_n=wash_mix,
        mix_vol=250,
        remaining=eth_remaining,
        mag_engage_height=mag_engage_height)

    # ### Dry
    protocol.comment('Removing wash and drying beads.')

    # This should:
    # - pick up tip in position 8
    # - pick up supernatant from magplate
    # - dispense in waste, position 11
    # - repeat
    # - trash tip
    # - leave magnet engaged

    # remove supernatant
    remove_supernatant(pipette_left,
                       mag_plate,
                       cols,
                       tiprack_wash,
                       waste['A1'],
                       super_vol=380,
                       rate=bead_flow,
                       bottom_offset=.5,
                       drop_tip=True)

    # dry
    protocol.delay(seconds=pause_dry)

    # ### Elute
    protocol.comment('Eluting DNA from beads.')

    # This should:
    # - disengage magnet
    # - pick up tip from position 6
    # - pick up reagents from column 2 of position 9
    # - dispense into magplate
    # - mix 10 times
    # - blow out, touch tip
    # - return tip to position 6
    # - wait (5 seconds)
    # - engage magnet
    # - wait (5 seconds)
    # - pick up tip from position 6
    # - aspirate from magplate
    # - dispense to position 3
    # - trash tip

    # transfer elution buffer to mag plate
    magblock.disengage()

    # add elution buffer and mix
    for col in cols:
        pipette_left.pick_up_tip(tiprack_elution_1.wells_by_name()[col])
        pipette_left.aspirate(50, reagents['A2'], rate=1)
        pipette_left.dispense(50, mag_plate[col].bottom(z=1))
        pipette_left.mix(10, 40, mag_plate[col].bottom(z=1))
        pipette_left.blow_out(mag_plate[col].top())
        pipette_left.touch_tip()
        # we'll use these same tips for final transfer
        pipette_left.return_tip()

    protocol.delay(seconds=pause_elute)
    # # start timer
    # t0 = clock()
    # # mix again
    # t_mix = 0
    # while t_mix < pause_elute():
    for col in cols:
        pipette_left.pick_up_tip(tiprack_elution_1.wells_by_name()[col])
        pipette_left.mix(10, 40, mag_plate[col].bottom(z=1))
        pipette_left.blow_out(mag_plate[col].top())
        pipette_left.touch_tip()
        # we'll use these same tips for final transfer
        pipette_left.drop_tip()
        # t_mix = clock() - t0

    # bind to magnet
    protocol.comment('Binding beads to magnet.')

    magblock.engage(height_from_base=mag_engage_height)

    protocol.delay(seconds=pause_mag)

    protocol.comment('Transferring eluted DNA to final plate.')
    for col in cols:
        pipette_left.pick_up_tip(tiprack_elution_2.wells_by_name()[col])
        pipette_left.aspirate(50, mag_plate[col].bottom(z=2), rate=bead_flow)
        pipette_left.dispense(50, eluate[col])
        pipette_left.blow_out(eluate[col].top())
        pipette_left.touch_tip()
        # we're done with these tips now
        pipette_left.drop_tip()

    magblock.disengage()