def add_antibody(protocol: ProtocolContext,
                 p300_multi: InstrumentContext,
                 reservoir: Labware,
                 tuberack: Labware,
                 plate: Labware,
                 wells: [[]]):
    """

    Args:
        protocol:
        p300_multi:
        reservoir: hopefully we will get a 12 well trough
        tuberack:
        wells: a column-wise list of lists of wells in use

    Returns:
        Nothing as of now

    """

    #  move liquid from reservoir to plate with p300 multi
    for _ in wells:
        i = 0
        p300_multi.transfer(source=reservoir, dest=plate.columns()[i], new_tip='never')
        i += 1
    #  pause for 2 hours
    protocol.delay(minutes=120)
Beispiel #2
0
def distribute_master_mix_p50(p50s: InstrumentContext, plates: [Labware],
                              tuberack: Labware, tipracks: [Labware],
                              facs: Labware):
    tubes = tuberack.wells()[:2]
    # to_remove is the number of wells to be removed from the final row. all prior rows will be assumed to be filled
    to_remove = 6
    to_remove = 12 - to_remove
    p50s.well_bottom_clearance.dispense = 10
    p50s.well_bottom_clearance.aspirate = 3
    # last_row is the index of the last row (rows() returns 2D list of rows by well)
    for plate in plates:
        start_row = 0
        num_rows = 2
        # first group @ row 0 (row A)
        last_row = num_rows
        for tube in tubes:
            group = plate.rows()[start_row:last_row]
            last_group = group[num_rows - 1][:to_remove]
            group[num_rows - 1] = last_group
            p50s.pick_up_tip()
            p50s.transfer(
                volume=50,
                source=tube,
                dest=group,
                new_tip='never',
            )  # comment out for actual runs. this is for test
            p50s.drop_tip()
            p50s.pick_up_tip()
            p50s.transfer(volume=50,
                          source=facs['A1'],
                          dest=group,
                          new_tip='never'
                          )  # comment out for actual runs. this is for test
            p50s.drop_tip()
            start_row += num_rows
            last_row += num_rows
def elisa_wash(protocol: protocol_api.ProtocolContext,
               p300m: InstrumentContext, reservoir: [Labware], plate: Labware,
               wells_to_fill: [[]], num_washes: int, wash_volume: int):
    """
    TODO: consider splitting into a load function and a remove function? this one is large. Is that modularity useful?
    # Maybe modularity is useful for multiple plates? Rather than changing this function to accommodate multiple plates
    # TODO: modularity here is almost certainly useful. Can reuse funcs for FACs prep
    Args:
        protocol: From robot
        p300m: P300 multichannel
        reservoir: A 12 well trough containing ELISA wash buffer
        plate: The plate to be washed
        num_washes: number of plate washes to perform
        wash_volume: volume of buffer to wash each well with

    Returns:
        nothing

    """
    # dispenses per aspiration to minimize movement and counter initialization
    dispenses_per_load = int(300 / wash_volume)
    # Calculate extra volume
    well_counter = 0
    vol_counter = 0
    # Pick up tips
    # TODO: adjust num presses and increment
    p300m.pick_up_tip(p300m.tip_racks[0].well('A1'), presses=3, increment=.05)
    for i1 in range(num_washes):
        # reset aspiration height
        p300m.well_bottom_clearance.aspirate = 1
        index = 0
        # TODO: add disposal volume?
        """
        ~~~~~~~~~~~~~~~~~~
        Handle adding wash to plate. Calculate max number of dispenses per source load.
        Loop and increment index appropriately. This calculation would be automatic, 
        but volume removed from source well has to be tracked manually to prevent empty.
        ~~~~~~~~~~~~~~~~~~
        """
        # for i2 in range(int(12/(dispenses_per_load))):
        # Establish a source well. well_counter should increment before well runs out of liquid
        # src must be established within this loop
        src = reservoir[0].columns()[well_counter]
        # location is a list of pairs defining locations of wells
        location = wells_to_fill

        print("location{}".format(location))
        # subset to locations in the distribution range (number of dispenses per aspiration)
        locs = location[index:index + 3]
        print(locs)
        # for all lists in locs, take the second (1) index aka the row
        # rows = plate.wells(*locs[2])
        # if multiple rows entered into parentheses, each row returned will be a list
        # so plate.row(1) yields [[wells B1-B12]] and plate.rows(1,2) yields [[wells B1-12], [C1-12]]
        """
        The logic below should underlie transforming csv files created by the plate mapper 
        into a format to access plate wells
        """
        rows = []
        cols = []
        for i in location:
            cols.append(i[0])
            if i[1] not in rows:
                rows.append(i[1])
        plate_map = plate.rows(*rows)
        updated = []
        for i in plate_map:
            # there shouldnt be a +1 for normal list slicing but apparently slicing is noninclusive or something
            updated.append(i[min(cols):max(cols) + 1])
        print(updated)

        # TODO: figure out volume count problem...works but not soon enough. well_counter iterates after two washes
        # TODO: maybe tips don't go down to bottom of well and that's why?
        for i in cols:
            p300m.distribute(volume=wash_volume,
                             source=src,
                             dest=rows[i],
                             new_tip='never',
                             disposal_volume=0,
                             blow_out=True)
        # Increment index by number of dispenses per aspiration
        index += dispenses_per_load
        # Count volume consumed from current trough well
        vol_counter += (.3 * 8)
        if vol_counter >= 9.7:
            # If most of the volume from the trough is gone, move to next well and reset volume count
            well_counter += 1
            vol_counter = 0
        # Tried distribute and keep getting tip already attached or tip not attached error
    """
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Mix and dispense most of the liquid into the trash. Manual flicking still necessary.
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    """
    # Set clearance for tip for aspiration
    p300m.well_bottom_clearance.aspirate = 0.1
    # Mix and transfer volume from plate to trash.
    p300m.transfer(
        volume=wash_volume,
        source=plate.rows()[0],
        dest=p300m.trash_container.wells(0),
        disposal_volume=100,
        new_tip='never',
        mix_before=(2, 80),
        aspirate_speed=5,
        dispense_speed=12,
    )
    p300m.home()
    protocol.pause(
        msg="{} washes done! Resume washing by clicking the 'Resume' button!".
        format(i1 + 1))
    protocol.comment(
        "{} washes complete! You may proceed with your protocol.".format(
            num_washes))
    p300m.return_tip()
    p300m.home()