def run(protocol: protocol_api.ProtocolContext): ################### SETTING UP ################### ## ## ## ヽ༼ຈل͜ຈ༽ノ LABWARE ヽ༼ຈل͜ຈ༽ノ ## ## ## ################################################## # Positions are: # 10 11 TRASH # 7 8 9 # 4 5 6 # 1 2 3 #Modules, plate and MAGNET HEIGHT magneto = protocol.load_module("magneticModuleV2", 6) deepPlate = magneto.load_labware("eppendorf_96_deepwell_2ml", label="Deep well") magnetHeight = 5 ######################################################################################################### ## We have tested appropriate height on GEN1 magdeck for different plates, these are the chosen ones ## ## ## ## Zymoresearch - "zymoresearch_96_deepwell_2.4ml" - 12.5mm ## ## Eppendorf - "eppendorf_96_deepwell_2ml" - 11.8 mm ## ## Starlab - "usascientific_96_wellplate_2.4ml_deep" - E2896-1810 11.4mm ## ## Macherey-Nagel - - 10mm ## ######################################################################################################### #Plates reagents = protocol.load_labware("nest_12_reservoir_15ml", 5, label="Reagents reservoir") waste = protocol.load_labware("nest_12_reservoir_15ml", 9, label="Liquid waste reservoir") outplate = protocol.load_labware("eppendorf96_skirted_150ul", 3, label="Output plate") #Tips - Ordered in the way they are used tiprack2 = protocol.load_labware("opentrons_96_filtertiprack_200ul", 4) p300 = protocol.load_instrument("p300_multi_gen2", "left", [tiprack2]) bottomHeight = 0.5 bottomMixHeight = 1 generalHeight = 5 topOffset = -5 moveSide = 0 def getMixingTopHeight(stringLabware, volume): labwareDefinition = protocol_api.labware.get_labware_definition( stringLabware) shape = labwareDefinition["wells"]["A1"]["shape"] if shape == "circular": diameter = labwareDefinition["wells"]["A1"]["diameter"] height = (math.pi * diameter**2) / volume else: width = labwareDefinition["wells"]["A1"]["xDimension"] length = labwareDefinition["wells"]["A1"]["yDimension"] height = volume / (width * length) def well_mix(vol, loc, reps, labwareName="eppendorf_96_deepwell_2ml", height=generalHeight, moveSide=0, bottomHeight=bottomMixHeight): """ Aspirates <vol> from bottom of well and dispenses it from <height> <reps> times loc1 is a position at 0.3mm over the bottom of the well loc2 is a position in the same x and y posiiton than loc1, but at <height>mm over the bottom of the well The idea here is to take liquid to the very bottom and pour it from a higher point, to mix things """ p300.flow_rate.aspirate = 100 p300.flow_rate.dispense = 300 height = getMixingTopHeight(labwareName, vol) loc1 = loc.bottom().move( types.Point(x=0 + moveSide, y=0, z=bottomHeight)) loc2 = loc.bottom().move(types.Point(x=0 + moveSide, y=0, z=height)) for _ in range(reps): p300.aspirate(vol, loc1) p300.dispense(vol, loc1) p300.flow_rate.aspirate = 50 p300.flow_rate.dispense = 150 p300.dispense(20, loc.top(topOffset)) p300.pick_up_tip(tiprack2["D1"]) well_mix(100, deepPlate["A1"], 10, labwareName="eppendorf_96_deepwell_2ml", moveSide=1, bottomHeight=0.8) magneto.disengage() #p300.pick_up_tip(tiprack2["D1"].top().move(types.Point(x=0, y=-36, z=0))) protocol.delay(seconds=20) p300.move_to(reagents["A1"].bottom().move( types.Point(x=0, y=0, z=bottomHeight))) protocol.delay(seconds=10) p300.move_to(deepPlate["A1"].bottom().move( types.Point(x=1, y=0, z=bottomMixHeight))) protocol.delay(seconds=5) p300.move_to(outplate["A1"].bottom().move(types.Point(x=0, y=0, z=5))) protocol.delay(seconds=10) p300.move_to(deepPlate["A1"].bottom().move( types.Point(x=-1, y=0, z=bottomHeight))) protocol.delay(seconds=5) well_mix(100, deepPlate["A1"], 10, moveSide=-1) p300.return_tip() magneto.disengage() protocol.delay(minutes=10) p300.transfer(500, outplate["A1"], outplate["A2"]) p300.transfer(500, reagents["A1"], reagents["A2"])
def run(protocol: protocol_api.ProtocolContext): slots_map = { '1': 'starlabpcrplateonws_96_wellplate_350ul', '2': 'opentrons_24_tuberack_generic_2ml_screwcap', '3': 'opentrons_24_tuberack_generic_2ml_screwcap', '5': 'opentrons_24_tuberack_generic_2ml_screwcap', '6': 'opentrons_24_tuberack_generic_2ml_screwcap', } # Configure tip racks and pipette r_pipette_name = 'p300_single' r_tiprack_slots = ['4'] # r_tiprack_name = 'opentrons_96_tiprack_300ul' r_tiprack_name = 'tipone_96_diytiprack_300ul' # l_pipette_name = 'p10_multi' # l_tiprack_slots = ['2'] # l_tiprack_name = 'geb_96_tiprack_10ul' labware_items = {} for slot, labware_item in slots_map.items(): labware_items.update({slot: protocol.load_labware(labware_item, slot)}) r_tip_racks = [ protocol.load_labware(r_tiprack_name, slot) for slot in r_tiprack_slots ] # l_tip_racks = [protocol.load_labware(l_tiprack_name, slot) for slot in l_tiprack_slots] r_pipette = protocol.load_instrument(instrument_name=r_pipette_name, mount='right', tip_racks=r_tip_racks) # l_pipette = protocol.load_instrument(instrument_name = l_pipette_name, # mount = 'left', tip_racks = l_tip_racks) inst_list = [ # '170$1_A1->2_A1', # '170$1_A2->2_A2', # '170$1_A3->2_A3', # '170$1_A4->2_A4', # '170$1_A5->2_A5', # '170$1_A6->2_A6', # '170$1_A7->2_B1', # '170$1_A8->2_B2', # '170$1_A9->2_B3', # '170$1_A10->2_B4', # '170$1_A11->2_B5', # '170$1_A12->2_B6', # '170$1_B1->2_C1', # '170$1_B2->2_C2', # '170$1_B3->2_C3', # '170$1_B4->2_C4', # '170$1_B5->2_C5', # '170$1_B6->2_C6', # '170$1_B7->2_D1', # '170$1_B8->2_D2', # '170$1_B9->2_D3', # '170$1_B10->2_D4', # '170$1_B11->2_D5', # '170$1_B12->2_D6', # '170$1_C1->3_A1', # '170$1_C2->3_A2', # '170$1_C3->3_A3', # '170$1_C4->3_A4', # '170$1_C5->3_A5', # '170$1_C6->3_A6', # '170$1_C7->3_B1', # '170$1_C8->3_B2', # '170$1_C9->3_B3', # '170$1_C10->3_B4', # '170$1_C11->3_B5', # '170$1_C12->3_B6', # '170$1_D1->3_C1', # '170$1_D2->3_C2', # '170$1_D3->3_C3', # '170$1_D4->3_C4', # '170$1_D5->3_C5', # '170$1_D6->3_C6', # '170$1_D7->3_D1', # '170$1_D8->3_D2', # '170$1_D9->3_D3', # '170$1_D10->3_D4', # '170$1_D11->3_D5', # '170$1_D12->3_D6', '170$1_E1->5_A1', '170$1_E2->5_A2', '170$1_E3->5_A3', '170$1_E4->5_A4', '170$1_E5->5_A5', '170$1_E6->5_A6', '170$1_E7->5_B1', '170$1_E8->5_B2', '170$1_E9->5_B3', '170$1_E10->5_B4', '170$1_E11->5_B5', '170$1_E12->5_B6', '170$1_F1->5_C1', '170$1_F2->5_C2', '170$1_F3->5_C3', '170$1_F4->5_C4', '170$1_F5->5_C5', '170$1_F6->5_C6', '170$1_F7->5_D1', '170$1_F8->5_D2', '170$1_F9->5_D3', '170$1_F10->5_D4', '170$1_F11->5_D5', '170$1_F12->5_D6', '170$1_G1->6_A1', '170$1_G2->6_A2', '170$1_G3->6_A3', '170$1_G4->6_A4', '170$1_G5->6_A5', '170$1_G6->6_A6', '170$1_G7->6_B1', '170$1_G8->6_B2', '170$1_G9->6_B3', '170$1_G10->6_B4', '170$1_G11->6_B5', '170$1_G12->6_B6', '170$1_H1->6_C1', '170$1_H2->6_C2', '170$1_H3->6_C3', '170$1_H4->6_C4', '170$1_H5->6_C5', '170$1_H6->6_C6', '170$1_H7->6_D1', '170$1_H8->6_D2', '170$1_H9->6_D3' ] for inst in inst_list: vol, path = inst.split('$') vol = int(vol) source, dest = path.split('->') source_slot, source_well = source.split('_') dest_slot, dest_well = dest.split('_') r_pipette.pick_up_tip(r_tip_racks[0].wells_by_name()[source_well]) r_pipette.aspirate( vol, labware_items[source_slot].wells_by_name()[source_well]) r_pipette.dispense( vol, labware_items[dest_slot].wells_by_name()[dest_well].top(-2)) r_pipette.aspirate(100) r_pipette.dispense(100) r_pipette.aspirate(100) r_pipette.dispense(100) r_pipette.blow_out() r_pipette.drop_tip()
def run(ctx: protocol_api.ProtocolContext): # confirm door is closed if not ctx.is_simulating(): confirm_door_is_closed(ctx) # define tips tips20 = [ ctx.load_labware('opentrons_96_filtertiprack_20ul', slot) for slot in ['6', '9', '8', '7'] ] tips300 = [ctx.load_labware('opentrons_96_filtertiprack_200ul', '3')] # define pipettes p20 = ctx.load_instrument('p20_single_gen2', 'right', tip_racks=tips20) p300 = ctx.load_instrument('p300_single_gen2', 'left', tip_racks=tips300) # tempdeck module tempdeck = ctx.load_module('tempdeck', '10') tempdeck.set_temperature(4) # check mastermix labware type if MM_LABWARE not in MM_LW_DICT: raise Exception('Invalid MM_LABWARE. Must be one of the following:\n' + '\n'.join(list(MM_LW_DICT.keys()))) # load mastermix labware mm_rack = ctx.load_labware(MM_LW_DICT[MM_LABWARE], '11', MM_LABWARE) # check mastermix tube labware type if MMTUBE_LABWARE not in MMTUBE_LW_DICT: raise Exception( 'Invalid MMTUBE_LABWARE. Must be one of the following:\n' + '\n'.join(list(MMTUBE_LW_DICT.keys()))) # This one is not loaded, it contains the raius of each tube to calculate volume height # check pcr plate if PCR_LABWARE not in PCR_LW_DICT: raise Exception( 'Invalid PCR_LABWARE. Must be one of the following:\n' + '\n'.join(list(PCR_LW_DICT.keys()))) # load pcr plate pcr_plate = tempdeck.load_labware(PCR_LW_DICT[PCR_LABWARE], 'PCR plate') # check source (elution) labware type if ELUTION_LABWARE not in EL_LW_DICT: raise Exception( 'Invalid ELUTION_LABWARE. Must be one of the following:\n' + '\n'.join(list(EL_LW_DICT.keys()))) # load elution labware if 'plate' in ELUTION_LABWARE: source_racks = ctx.load_labware(EL_LW_DICT[ELUTION_LABWARE], '1', 'RNA elution labware') else: source_racks = [ ctx.load_labware(EL_LW_DICT[ELUTION_LABWARE], slot, 'RNA elution labware ' + str(i + 1)) for i, slot in enumerate(['4', '1', '5', '2']) ] # setup sample sources and destinations sources, dests = get_source_dest_coordinates(ELUTION_LABWARE, source_racks, pcr_plate) # prepare mastermix if PREPARE_MASTERMIX: mm_tube = prepare_mastermix(MM_TYPE, mm_rack, p300, p20) else: mm_tube = mm_rack.wells()[0] if TRANSFER_MASTERMIX: homogenize_mm(mm_tube, p300) # transfer mastermix if TRANSFER_MASTERMIX: transfer_mastermix(mm_tube, dests, VOLUME_MMIX, p300, p20) # transfer samples to corresponding locations if TRANSFER_SAMPLES: transfer_samples(ELUTION_LABWARE, sources, dests, p20) finish_run()
def run(protocol: protocol_api.ProtocolContext): """ Pipette 30uL of water from a 5mL tube to 12 PCR strips. Using a new tip for every step so that we can check if there is no big difference between volumes from different pipette tip locations. """ # ============================================================================= # ======================LOADING LABWARE AND PIPETTES=========================== # ============================================================================= ## For available labware see "labware/list_of_available_labware". ## # Pipette tips ##### !!! OPTION 1: ROBOT tip_one_300 = protocol.load_labware( 'tipone_96_tiprack_300ul', #labware definition 1, #deck position '300tips') #custom name ##### !!! OPTION 2: SIMULATOR # with open("labware/tipone_96_tiprack_300ul/" # "tipone_96_tiprack_300ul.json") as labware_file: # labware_def_tips = json.load(labware_file) # tip_one_300 = protocol.load_labware_from_definition( # labware_def_tips, #variable derived from opening json # 1, #deck position # '300tips') #custom name # Tube_racks & plates ##### !!! OPTION 1: ROBOT source_tube = protocol.load_labware( 'eppendorfscrewcap_15_tuberack_5000ul', #labware def 2, #deck position 'source_tube') #custom name strips_1 = protocol.load_labware( 'pcrstrips_96_wellplate_200ul', #labware definition 7, #deck position 'strips_1') #custom name strips_2 = protocol.load_labware( 'pcrstrips_96_wellplate_200ul', #labware definition 4, #deck position 'strips_2') #custom name strips_3 = protocol.load_labware( 'pcrstrips_96_wellplate_200ul', #labware definition 8, #deck position 'strips_3') #custom name strips_4 = protocol.load_labware( 'pcrstrips_96_wellplate_200ul', #labware definition 5, #deck position 'strips_4') #custom name ##### !!! OPTION 2: SIMULATOR # with open("labware/eppendorfscrewcap_15_tuberack_5000ul/" # "eppendorfscrewcap_15_tuberack_5000ul.json") as labware_file: # labware_def_5mL = json.load(labware_file) # source_tube = protocol.load_labware_from_definition( # labware_def_5mL, #variable derived from opening json # 2, #deck position # 'source_tube') #custom name # with open("labware/pcrstrips_96_wellplate_200ul/" # "pcrstrips_96_wellplate_200ul.json") as labware_file: # labware_def_pcrstrips = json.load(labware_file) # strips_1 = protocol.load_labware_from_definition( # labware_def_pcrstrips, #variable derived from opening json # 7, #deck position # 'strips_1') #custom name # strips_2 = protocol.load_labware_from_definition( # labware_def_pcrstrips, #variable derived from opening json # 4, #deck position # 'strips_2') #custom name # strips_3 = protocol.load_labware_from_definition( # labware_def_pcrstrips, #variable derived from opening json # 8, #deck position # 'strips_3') #custom name # strips_4 = protocol.load_labware_from_definition( # labware_def_pcrstrips, #variable derived from opening json # 5, #deck position # 'strips_4') #custom name # Pipettes p300 = protocol.load_instrument( 'p300_single_gen2', #instrument definition 'right', #mount position tip_racks=[tip_one_300]) #assigned tiprack # ============================================================================= # ==========================VARIABLES TO SET#!!!=============================== # ============================================================================= start_vol = 3000 ## The start_vol is the volume (ul) that is in the source labware at ## ## the start of the protocol. ## dispension_vol = 30 ## The dispension_vol is the volume (ul) that needs to be aliquoted ## ## into the destination wells/tubes. ## p300.starting_tip = tip_one_300.well('A1') ## The starting_tip is the location of first pipette tip in the box ## container = 'tube_5mL' ## The container variable is needed for the volume tracking module. ## ## It tells the module which dimensions to use for the calculations ## ## of the pipette height. It is the source labware from which liquid ## ## is aliquoted. ## ## There are several options to choose from: ## ## 'tube_1.5ml', 'tube_2mL', 'tube_5mL', 'tube_15mL', 'tube_50mL' ## source = source_tube['C1'] # Destination wells============================================================ destinations = [] ## Create an empty list to append wells to ## destination_columns = ([ strips_1.columns_by_name()[column_name] for column_name in ['2', '7', '11'] ] + [ strips_2.columns_by_name()[column_name] for column_name in ['2', '7', '11'] ] + [ strips_3.columns_by_name()[column_name] for column_name in ['2', '7', '11'] ] + [ strips_4.columns_by_name()[column_name] for column_name in ['2', '7', '11'] ]) ## Make a list of columns, this is a list of lists! ## for column in destination_columns: for well in column: destinations.append(well) # ============================================================================= # ==========================PREDIFINED VARIABLES=============================== # ============================================================================= aspiration_vol = dispension_vol ## The aspiration_vol is the volume (ul) that is aspirated from the ## ## container. ## ##### Variables for volume tracking start_height = vt.cal_start_height(container, start_vol) ## Call start height calculation function from volume tracking module.## current_height = start_height ## Set the current height to start height at the beginning of the ## ## protocol. ## # ============================================================================= # =================================ALIQUOTING================================== # ============================================================================= ## For each column in destination_wells, pick up a tip, than for each ## ## well in these columns pipette mix, and after the+ column drop the tip## ## Repeat untill all columns in the list are done. ## for well in destinations: ## Name all the wells in the plate 'well', for all these do: ## p300.pick_up_tip() current_height, pip_height, bottom_reached = vt.volume_tracking( container, dispension_vol, current_height) ## The volume_tracking function needs the arguments container, ## ## dispension_vol, and the current_height which we have set in ## ## this protocol. With those variables, the function updates ## ## the current_height, the pip_height and calculates the ## ## delta_height of the liquid after the next aspiration step. ## if bottom_reached: aspiration_location = source.bottom(z=1) #!!! protocol.comment("You've reached the bottom!") else: aspiration_location = source.bottom(pip_height) #!!! ## If the level of the liquid in the next run of the loop will ## ## be smaller than 1 we have reached the bottom of the tube. ## ## To prevent the pipette from crashing into the bottom, we ## ## tell it to go home and pause the protocol so that this can ## ## never happen. Set the location of where to aspirate from. ## ## Because we put this in the loop, the location will change ## ## to the newly calculated height after each pipetting step. ## p300.aspirate(aspiration_vol, aspiration_location) ## Aspirate the amount specified in aspiration_vol from the ## ## location specified in aspiration_location. ## p300.dispense(dispension_vol, well) ## Dispense the amount specified in dispension_vol to the ## ## location specified in well (so a new well every time the ## ## loop restarts) ## p300.drop_tip() # =============================================================================
def run(protocol: protocol_api.ProtocolContext): tiprack1 = protocol.load_labware("opentrons_96_tiprack_20ul",'1') p20 = protocol.load_instrument('p20_single_gen2',"right",tip_racks=[tiprack1]) p20.pick_up_tip() p20.drop_tip()
def run(protocol: protocol_api.ProtocolContext): # LABWARE fuge_rack = protocol.load_labware('vwr_24_tuberack_1500ul', '1') std_rack = protocol.load_labware('vwr_24_tuberack_1500ul', '2') tiprack300 = protocol.load_labware('opentrons_96_filtertiprack_200ul', '8') tiprack20 = protocol.load_labware('opentrons_96_filtertiprack_20ul', '9') tempdeck = protocol.load_module( 'tempdeck', '10') # have this so I don't have to move it off holder_1 = protocol.load_labware( '8wstriptubesonfilterracks_96_aluminumblock_250ul', '3') holder_2 = protocol.load_labware( '8wstriptubesonfilterracks_96_aluminumblock_250ul', '6') stds_plate = tempdeck.load_labware('abi_96_wellplate_250ul') # PIPETTES p300 = protocol.load_instrument('p300_single_gen2', 'left', tip_racks=[tiprack300]) p20 = protocol.load_instrument('p20_single_gen2', 'right', tip_racks=[tiprack20]) # REAGENTS std_1 = std_rack['A1'] # 900ul Water std_2 = std_rack['A2'] # 900ul water std_3 = std_rack['A3'] # 900ul water std_4 = std_rack['A4'] # 900ul water std_5 = std_rack['A5'] # 900ul water std_6 = std_rack['A6'] # 900ul water std_7 = std_rack['B1'] # 900ul water std_8 = std_rack['B2'] # 900ul water std_9 = std_rack['B3'] # 900ul water std_10 = std_rack['B4'] # 900ul water std_11 = std_rack['B5'] # 900ul water std_12 = std_rack['B6'] # 900ul water std_13 = std_rack['C1'] # 900ul water std_14 = std_rack['C2'] # 900ul water std_15 = std_rack['C3'] # 900ul water pos_control = fuge_rack['A1'] # 100-1000ul pos control @1uM mmp_tube = fuge_rack['A2'] #500 uL of master mixs and 400uL of primers waste = fuge_rack['D6'] # waste water = fuge_rack['A3'] # 100 uL water # LISTS std_wells = [ std_1, std_2, std_3, std_4, std_5, std_6, std_7, std_8, std_9, std_10, std_11, std_12, std_13, std_14, std_15 ] std_conc = [ std_4, std_5, std_6, std_7, std_8, ] cols = [1, 3, 5, 7, 9, 11] rows = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'] ### COMMANDS ###### #Make std dilution series #Make 10nM pos control, std_1 p300.transfer( 100, pos_control.bottom(2), #1uM std_1.bottom(20), mix_after=(3, 200), # remove residual fluid from tip touch_tip=False) # serial dilutions in microfuge tubes, 10% diliutions for i in range(len(std_wells) - 1): h_mix = 20 p300.pick_up_tip() p300.mix(2, 200, std_wells[i].bottom(8)) # mix low p300.mix(2, 200, std_wells[i].bottom(14)) # mix mid p300.mix(5, 200, std_wells[i].bottom(h_mix)) #mix hi p300.aspirate(100, std_wells[i].bottom(h_mix), rate=0.4) p300.touch_tip() p300.dispense( 100, std_wells[i + 1].bottom(14)) # better mixing with mid dispense p300.blow_out( std_wells[i + 1].bottom(h_mix)) # blow out just below the surface p300.drop_tip() if i == len(std_wells) - 2: # last tube p300.pick_up_tip() p300.mix(2, 200, std_wells[i + 1].bottom(8)) # mix low p300.mix(2, 200, std_wells[i + 1].bottom(14)) # mix mid p300.mix(5, 200, std_wells[i + 1].bottom(h_mix)) #mix hi p300.blow_out( std_wells[i + 1].bottom(h_mix)) # blow out just below the surface p300.drop_tip() #add master mix and primers to PRC tubes for col in cols[0:2]: p20.pick_up_tip() for row in rows: p20.aspirate(18, mmp_tube) p20.touch_tip(v_offset=-5) p20.dispense(18, holder_1[row + str(col)]) p20.drop_tip() #add first 4 standards to upper half of tubes count = 0 # keep track of standard for row in rows: p20.pick_up_tip() p20.aspirate(6, std_conc[count]) #take from standand p20.touch_tip() for col in cols[0:2]: p20.dispense(2, holder_1[row + str(col)]) # dispense in PCR tubes p20.touch_tip() p20.dispense(2, waste) p20.blow_out(waste) p20.drop_tip() count = count + 1 if count == 4: break # #add first 4 standards to lower half of tubes count = 0 #reset count for row in rows[4:]: p20.pick_up_tip() p20.aspirate(4, std_conc[count]) p20.touch_tip() for col in cols[0:1]: p20.dispense(2, holder_1[row + str(col)]) p20.touch_tip() p20.dispense(2, waste) p20.blow_out(waste) p20.drop_tip() count = count + 1 if count == 4: break #add final standard for row in rows[4:7]: p20.pick_up_tip() p20.aspirate(8, std_conc[count]) p20.touch_tip() for col in cols[1:2]: p20.dispense(2, holder_1[row + str(col)]) p20.touch_tip() p20.dispense(2, waste) p20.blow_out(waste) p20.drop_tip() # add water to last 3 wells for row in rows[7:8]: p20.pick_up_tip() p20.aspirate(4, water) p20.touch_tip() for col in cols[1:2]: p20.dispense(2, holder_1[row + str(col)]) p20.touch_tip() p20.dispense(2, waste) p20.blow_out(waste) p20.drop_tip()
def run(ctx: protocol_api.ProtocolContext): STEP = 0 STEPS = { # Dictionary with STEP activation, description and times 1: {'Execute': True, 'description': 'Transferir muestras al deepwell ('+str(VOLUME_SAMPLE)+' ul)'}, } for s in STEPS: # Create an empty wait_time if 'wait_time' not in STEPS[s]: STEPS[s]['wait_time'] = 0 #Folder and file_path for log time if not ctx.is_simulating(): folder_path = '/var/lib/jupyter/notebooks/' + run_id if not os.path.isdir(folder_path): os.mkdir(folder_path) file_path = folder_path + '/Station_A_time_log.txt' # Define Reagents as objects with their properties class Reagent: def __init__(self, name, flow_rate_aspirate, flow_rate_dispense, delay): self.name = name self.flow_rate_aspirate = flow_rate_aspirate self.flow_rate_dispense = flow_rate_dispense self.delay = delay class Reagent2: def __init__(self, name, flow_rate_aspirate, flow_rate_dispense, reagent_reservoir_volume, delay, num_wells, tip_recycling='none'): self.name = name self.flow_rate_aspirate = flow_rate_aspirate self.flow_rate_dispense = flow_rate_dispense self.reagent_reservoir_volume = reagent_reservoir_volume self.delay = delay self.num_wells = num_wells self.col = 0 self.vol_well = 0 self.tip_recycling = tip_recycling self.vol_well_original = reagent_reservoir_volume / num_wells # Reagents and their characteristics Samples = Reagent(name='Samples', flow_rate_aspirate=50, flow_rate_dispense=100, delay=0) Lysis = Reagent2(name='Lysis', flow_rate_aspirate=50, flow_rate_dispense=100, reagent_reservoir_volume=48000, num_wells=1, delay=0) ctx.comment(' ') ctx.comment('###############################################') ctx.comment('VALORES DE VARIABLES') ctx.comment(' ') ctx.comment('Número de muestras: ' + str(NUM_SAMPLES)) ctx.comment('Número de ciclos de recogida (pools): ' + str(NUM_POOLS)) ctx.comment('Volumen de muestra a mover: ' + str(VOLUME_SAMPLE) + ' ul') ctx.comment('Foto-sensible: ' + str(PHOTOSENSITIVE)) ctx.comment(' ') ctx.comment('###############################################') ctx.comment('VOLÚMENES PARA ' + str(NUM_SAMPLES) + ' MUESTRAS') ctx.comment(' ') ctx.comment('###############################################') ctx.comment(' ') ################## # Custom functions def move_vol_multichannel(pipet, reagent, source, dest, vol, air_gap_vol, x_offset, pickup_height, 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 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 ''' # 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=-10) def divide_destinations(l, n): # Divide the list of destinations in size n lists. for i in range(0, len(l), n): yield l[i:i + n] def custom_mix(pipet, reagent, location, vol, rounds, blow_out, mix_height, x_offset, source_height=5, touch_tip=False): ''' 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 if touch_tip == True: pipet.touch_tip(speed=20, v_offset=-10) def generate_source_table(source, source_extra): ''' Concatenate the wells frome the different origin racks ''' num_cols = math.ceil(NUM_SAMPLES / 9) s = [] for i in range(num_cols): if i < 5: s += source[0].columns()[i] + source[1].columns( )[i] + source[2].columns()[i] else: s += source[3].columns()[i - 5] + source[4].columns()[ i - 5] + source[5].columns()[i - 5] return s def distribute_custom(pipette, reagent, 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), rate=reagent.flow_rate_aspirate) pipette.move_to(src.top(z=5)) pipette.aspirate(air_gap_vol_sample, rate=reagent.flow_rate_aspirate) # air gap for d in dest: pipette.dispense(volume + air_gap_vol_sample, d.top(), rate=reagent.flow_rate_dispense) pipette.move_to(d.top(z=5)) pipette.aspirate(air_gap_vol_sample, rate=reagent.flow_rate_dispense) # air gap try: pipette.blow_out(waste_pool.wells()[0].bottom(pickup_height + 3)) except: pipette.blow_out(waste_pool.top(pickup_height + 3)) return (len(dest) * volume) def pick_up_tip(pip, tips): nonlocal tip_track #if not ctx.is_simulating(): if recycle_tip: pip.pick_up_tip(tips[0].wells()[0]) else: if tip_track['counts'][pip] >= tip_track['maxes'][pip]: for i in range(3): ctx._hw_manager.hardware.set_lights(rails=False) ctx._hw_manager.hardware.set_lights(button=(1, 0, 0)) time.sleep(0.3) ctx._hw_manager.hardware.set_lights(rails=True) ctx._hw_manager.hardware.set_lights(button=(0, 0, 1)) time.sleep(0.3) ctx._hw_manager.hardware.set_lights(button=(0, 1, 0)) ctx.pause('Cambiar ' + str(pip.max_volume) + ' µl tipracks antes del pulsar Resume.') pip.reset_tipracks() tip_track['counts'][pip] = 0 tip_track['num_refills'][pip] += 1 pip.pick_up_tip() def drop_tip(pip): if recycle_tip == True: pip.return_tip() else: pip.drop_tip(home_after=False) tip_track['counts'][pip] += 8 if '8-Channel' in str(pip) else 1 def start_run(): ctx.comment(' ') ctx.comment('###############################################') ctx.comment('Empezando protocolo') if PHOTOSENSITIVE == False: ctx._hw_manager.hardware.set_lights(button=True, rails=True) else: ctx._hw_manager.hardware.set_lights(button=True, rails=False) now = datetime.now() # dd/mm/YY H:M:S start_time = now.strftime("%Y/%m/%d %H:%M:%S") return start_time def finish_run(): ctx.comment('###############################################') ctx.comment('Protocolo finalizado') ctx.comment(' ') #Set light color to blue ctx._hw_manager.hardware.set_lights(button=True, rails=False) now = datetime.now() # dd/mm/YY H:M:S finish_time = now.strftime("%Y/%m/%d %H:%M:%S") if PHOTOSENSITIVE == False: for i in range(10): ctx._hw_manager.hardware.set_lights(button=False, rails=False) time.sleep(0.3) ctx._hw_manager.hardware.set_lights(button=True, rails=True) time.sleep(0.3) else: for i in range(10): ctx._hw_manager.hardware.set_lights(button=False, rails=False) time.sleep(0.3) ctx._hw_manager.hardware.set_lights(button=True, rails=False) time.sleep(0.3) ctx._hw_manager.hardware.set_lights(button=True, rails=False) ctx.comment('Puntas de 200 ul utilizadas: ' + str(tip_track['counts'][m300]) + ' (' + str(round(tip_track['counts'][m300] / 96, 2)) + ' caja(s))') ctx.comment('Puntas de 1000 ul utilizadas: ' + str(tip_track['counts'][p1000]) + ' (' + str(round(tip_track['counts'][p1000] / 96, 2)) + ' caja(s))') ctx.comment('###############################################') return finish_time def log_step_start(): ctx.comment(' ') ctx.comment('###############################################') ctx.comment('PASO ' + str(STEP) + ': ' + STEPS[STEP]['description']) ctx.comment('###############################################') ctx.comment(' ') return datetime.now() def log_step_end(start): end = datetime.now() time_taken = (end - start) STEPS[STEP]['Time:'] = str(time_taken) ctx.comment(' ') ctx.comment('Paso ' + str(STEP) + ': ' + STEPS[STEP]['description'] + ' hizo un tiempo de ' + str(time_taken)) ctx.comment(' ') #################################### # load labware and modules #################################### if NUM_SAMPLES <= 45: rack_num = 3 ctx.comment('Los racks a utilizar son: ' + str(rack_num)) else: rack_num = 6 ctx.comment('Los racks a utilizar son: ' + str(rack_num)) source_racks = [ ctx.load_labware('opentrons_15_tuberack_falcon_15ml_conical', slot, 'Source Tube Rack with snapcap ' + str(i + 1)) for i, slot in enumerate(['7', '4', '1', '8', '5', '2'][:rack_num]) ] source_racks_extra = ctx.load_labware( 'opentrons_10_tuberack_falcon_4x50ml_6x15ml_conical', '9', 'Lysis Tube Rack') Lysis.reagent_reservoir = source_racks_extra.wells_by_name()['A3'] ################################## # Destination plate dest_deepwell_plate = ctx.load_labware('nest_96_wellplate_2ml_deep', '6', 'NEST 96 Deepwell Plate 2mL') #################################### # Load tip_racks tips1000 = [ ctx.load_labware('opentrons_96_filtertiprack_1000ul', slot, '1000µl filter tiprack') for slot in ['11'] ] tips300 = [ ctx.load_labware('opentrons_96_filtertiprack_200ul', slot, '200µl filter tiprack') for slot in ['10'] ] ################################################################################ # Setup sources and destinations sources_sample = generate_source_table(source_racks, source_racks_extra)[0:NUM_SAMPLES] dests_deepwell = dest_deepwell_plate.wells()[0:NUM_SAMPLES] p1000 = ctx.load_instrument('p1000_single_gen2', 'right', tip_racks=tips1000) # load P1000 pipette m300 = ctx.load_instrument('p300_multi_gen2', 'left', tip_racks=tips300) # load P1000 pipette tip_track = { 'counts': { m300: 0, p1000: 0 }, 'maxes': { m300: 96 * len(m300.tip_racks), p1000: 96 * len(p1000.tip_racks) }, #96 tips per tiprack * number or tipracks in the layout 'num_refills': { m300: 0, p1000: 0 } } # used tip counter and set maximum tips available start_run() ############################################################################ # STEP 1: ADD SAMPLES TO DEEPWELL ############################################################################ STEP += 1 if STEPS[STEP]['Execute'] == True: start = log_step_start() for pool in range(NUM_POOLS): for s, d in zip(sources_sample, dests_deepwell): if not p1000.hw_pipette['has_tip']: pick_up_tip(p1000, tips1000) move_vol_multichannel(p1000, reagent=Samples, source=s, dest=d, vol=VOLUME_SAMPLE, air_gap_vol=air_gap_vol_sample, x_offset=x_offset, pickup_height=4, disp_height=-10, blow_out=True, touch_tip=False) p1000.air_gap(air_gap_vol_sample) drop_tip(p1000) #pausar if pool < NUM_POOLS - 1: ctx.pause( 'Cambiar las muestras para el pooling y cambiar el tipRacks de 1000 µl antes del pulsar Resume.' ) log_step_end(start) # Export the time log to a tsv file if not ctx.is_simulating(): with open(file_path, 'w') as f: f.write( 'STEP\texecution\tdescription\twait_time\texecution_time\n') for key in STEPS.keys(): row = str(key) for key2 in STEPS[key].keys(): row += '\t' + format(STEPS[key][key2]) f.write(row + '\n') f.close() ############################################################################ finish_run()
def run(protocol: protocol_api.ProtocolContext): #Modules, plate and MAGNET HEIGHT magneto = protocol.load_module("magneticModuleV2", 6) deepPlate = magneto.load_labware("eppendorf_96_deepwell_2ml", label="Deep well") magnetHeight = 6.7 ######################################################################################################### ## We have tested appropriate height on GEN1 magdeck for different plates, these are the chosen ones ## ## ## ## Zymoresearch - "zymoresearch_96_deepwell_2.4ml" - 12.5mm ## ## Eppendorf - "eppendorf_96_deepwell_2ml" - 11.8 mm ## ## Starlab - "usascientific_96_wellplate_2.4ml_deep" - E2896-1810 11.4mm ## ## Macherey-Nagel - - 10mm ## ######################################################################################################### #Plates reagents = protocol.load_labware("nest_12_reservoir_15ml", 5, label="Reagents reservoir") waste = protocol.load_labware("nest_12_reservoir_15ml", 9, label="Liquid waste reservoir") outplate = protocol.load_labware("eppendorf96_skirted_150ul", 1, label="Output plate") #Tips - Ordered in the way they are used parkingRack = protocol.load_labware("opentrons_96_filtertiprack_200ul", 3) tiprack2 = protocol.load_labware("opentrons_96_filtertiprack_200ul", 2) tiprack4 = protocol.load_labware("opentrons_96_filtertiprack_200ul", 4) tiprack7 = protocol.load_labware("opentrons_96_filtertiprack_200ul", 7) tiprack8 = protocol.load_labware("opentrons_96_filtertiprack_200ul", 8) tiprack10 = protocol.load_labware("opentrons_96_filtertiprack_200ul", 10) tipracks = [tiprack10, tiprack8, tiprack7, tiprack4, tiprack2] availableTips = [] for rack in tipracks: for i in range(1, 13): availableTips.append(rack["A" + str(i)]) #To take a tip, just use availableTips.pop() and voila! #There are enough tips for 6 samples, and a tiprack will end up half-full #Tips are taken from right to left instead of the normal way #I am using this dictionary method because it makes it easier to modify later the script for 96 samples/ #Pipettes p300 = protocol.load_instrument("p300_multi_gen2", "left") #RUN SETTINGS runColumns = 2 # Range 1-6. Samples should be a multiple of 8, or you will waste reagents. mixRepeats = 15 # Used everytime there is mixing, except when mixing beads. beadsMixRepeats = 10 # Used when mixing beads in reservoir. This happens when pipetting column 1, 3 and 6. waterMixRepeats = 20 # Used when mixing elute. mixdownReps = 10 mixMovementReps = 10 #Mixing settings washMixing = 100 # volume (ul) waterMixing = 25 # volume (ul) mixingOffset = 1 # Positive values mean to the right. Relative to center (mm) bottomHeight = 0.5 # Distance relative to real labware's bottom. Used when removing supernatant and moving elution. bottomMixHeight = 0.8 # Distance relative to real labware's bottom. Used when mixing SamplePlusProteinaseHeight = 3 # For a volume of 260.. SamplePlusProteinasePlusBeadsHeight = 5.75 # For a volume of 465... generalHeight = 4 # Used always except when mixing beads in reservoir - Units relative to well bottom (mm). For a vol of 280... beadsHeight = 10 # Used when mixing beads in reservoir - Units relative to well bottom (mm). When mixing beads in the reagent well - Maybe I should modify this and make it depend on runColumns #Incubation times - Minutes incubationProteinase = 10 incubationBeadsNoMagnet = 5 # After adding the beads, we incubate them for 5 min without magnet. incubationBeadsMagnet = 5 * 2 incubationWash = 3 * 2 incubationDry = 10 # After removing final wash, the beads are left to dry for a while. incubationWater = 5 # After mixing. No magnet. incubationWaterMagnet = 1 * 2 # After incubationWater. #Transference volumes - ul originalVol = 140 #This is not used for transfers, it is here mostly to make volumes clearer to understand proteinaseVol = 112 beadsVol = 143.5 washVol = 280 #Used for WBE and Ethanol1 and Ethanol2 dilutionVol = 50 initialSupernatant = originalVol + proteinaseVol + beadsVol #Reagent position in reservoir - Positions go from A1 to A12 (Left to right) proteinase = reagents["A1"] beads = reagents["A2"] WBE = reagents["A3"] ethanol1 = reagents["A4"] ethanol2 = reagents["A5"] water = reagents["A12"] ######################################################################################################### ## Use these formulae to identify how much volume you need based on number of columns ## ## Each reservoir well has dimensions W=8.20, L=127.76, H=31.40. To make sure there is ## ## a pool of extra content with 0.5mm of height, add 292ul (300) extra (8.20*127.76*0.05) ## ## ## ## Proteinase = (896 * runColumns) + 292 ul ## ## Beads = (1152 * Columns) + 292 ul ## ## WBE = (2240 * Columns) + 292 ul ## ## Ethanol1 = (2240 * Columns) + 292 ul ## ## Ethanol2 = (2240 * Columns) + 292 ul ## ## Water = (640 * Columns) + 292 ul ## ######################################################################################################### ################### SETTING UP ################### ## ## ## ヽ༼ຈل͜ຈ༽ノ ADVANCED VARIABLES ヽ༼ຈل͜ຈ༽ノ ## ## ## ################################################## #Column accesion list - As we wont work in all physically available columns, this list makes it easier to manage columnID = ["A1", "A2", "A3", "A4", "A9", "A11"] # These are the columns that can be used columnID = columnID[: runColumns] # Here we trim the list, to get only the number of columns chosen in runColumns #Pipette settings tipVolume = 180 # max volume to be transported in a single trip. These tips are 200ul, but if we use the entire volumen, it might touch the filter topOffset = -5 # I use this to make sure the tip stays inside the well, to avoid it spilling out while dispensing p300.flow_rate.aspirate = 50 # Flow rate in ul / second p300.flow_rate.dispense = 150 p300.flow_rate.blow_out = 200 #Flows are reduced compared to default values to avoid the production of air or foam during handling. #Volume used when mixing beads (ul) if runColumns == 1: beadsMixing = 140 else: beadsMixing = tipVolume ################### SETTING UP ################### ## ## ##(づ。◕‿‿◕。)づ FUNCTIONS (づ。◕‿‿◕。)づ ## ## ## ################################################## def clock(time): """ The uncertainty of not knowing how much time is left in an incubation is horrible. This makes it more bearable. This function takes the duration of the incubation and outputs a message every minute to keep track of the time more easily """ while time > 0: time -= 1 protocol.delay(minutes=1) print("Only %s minutes more! Hold in there!" % time) def meneillo(pipette, pos, reps=10, distance=0.25): pipette.move_to(pos) for _ in range(reps): p300.move_to(pos.move(types.Point(x=distance, y=0, z=0))) p300.move_to(pos.move(types.Point(x=-distance, y=0, z=0))) def clean_tips(pipette, dump): protocol.delay(seconds=2) meneillo( pipette, dump.top(topOffset) ) #In case something is TheOppositeOfDense and just drips down pipette.dispense( 20 ) #Make sure we expel everything that must be expelled. We dont want to move droplets around. def remove_tip(pipette, tip): """ Originally, I had a special behaviour to drop the tips, but I stopped using it. I keep this function because it makes it easy to change drop_tip() to return_tip() for test runs """ pipette.drop_tip() def retrieve_tip(pipette, tip): """ Originally, the robot took a tip, went to the top of the well it was going to work with, and aspired 20 ul there, but now we are making it aspire 20 ul after taking the tip """ pipette.pick_up_tip(tip) def well_mix(vol, loc, repsdown=mixdownReps, repsmovement=mixMovementReps, yOffset=0.75, height=generalHeight, moveSide=0, bottomHeight=bottomMixHeight): """ Aspirates <vol> from bottom of well and dispenses it from <height> <reps> times loc1 is a position at 0.3mm over the bottom of the well loc2 is a position in the same x and y posiiton than loc1, but at <height>mm over the bottom of the well The idea here is to take liquid to the very bottom and pour it from a higher point, to mix things """ p300.flow_rate.aspirate = 1000 p300.flow_rate.dispense = 1000 for _ in range(repsdown): p300.aspirate( vol, loc.bottom().move( types.Point(x=0 + moveSide, y=yOffset, z=bottomHeight))) p300.dispense( vol, loc.bottom().move( types.Point(x=0 + moveSide, y=yOffset, z=bottomHeight))) yOffset = -yOffset for _ in range(repsmovement): p300.aspirate( vol, loc.bottom().move( types.Point(x=0 + moveSide, y=yOffset, z=bottomHeight))) yOffset = -yOffset p300.dispense( vol, loc.bottom().move( types.Point(x=0 + moveSide, y=yOffset, z=height))) p300.dispense(20, loc.top(topOffset)) p300.flow_rate.aspirate = 50 p300.flow_rate.dispense = 150 def remove_supernatant(vol, columnID, wasteID, reagentName="Something", pipette=p300, newtip=False): """ While <vol> is bigger than <tipVolume>, it divides it in ceilling(<vol>/<tipVolume>) trips. (So, if it is 396ul, we have 2 180ul trips and a 36ul trip) Flow rate is in ul/second In the move() function, positive X means 'move to the right'. With the wells we use (Column 1,3,5,7,9 and 11) pellet is placed to the right, so we use a small offset to the left """ p300.flow_rate.aspirate = 20 # In this case we reduce the flow even more to make sure the precipitate is okay. We don't wanna bother the lad protocol.comment( "\n\nREMOVING STEP: Removing %s ul of supernatant (%s) while magnet is still engaged" % (vol, reagentName)) dump = waste[wasteID] for index, ID in enumerate(columnID): if (ID == "A2" or ID == "A4"): blabla = 1 else: blabla = -1 if newtip == False: currentip = parkingRack[ID] else: currentip = availableTips.pop() dump = waste[ID] src = deepPlate[ID] retrieve_tip(pipette, currentip) tvol = vol while tvol > tipVolume: p300.dispense(20, src.top(topOffset)) p300.transfer(tipVolume, src.bottom().move( types.Point(x=blabla, y=0, z=bottomHeight)), dump.top(topOffset), new_tip="never") #Slightly to the left meneillo( p300, dump.top(topOffset) ) #In case something is TheOppositeOfDense and just drips down p300.dispense( 20 ) #Make sure we expel everything that must be expelled. We dont want to move droplets around. tvol -= tipVolume p300.dispense(20, src.top(topOffset)) p300.transfer(tvol, src.bottom().move( types.Point(x=blabla, y=0, z=bottomHeight)), dump.top(topOffset), new_tip="never") clean_tips(pipette, dump) remove_tip(pipette, currentip) p300.flow_rate.aspirate = 50 def slow_transfer(vol, reagent, columnID, reagentName, mixVol=washMixing, downRepeats=mixdownReps, movementRepeats=mixMovementReps, mixReagent=False, altura=generalHeight, magnetTime=True, incubationTime=incubationWash, moveSide=0, extraVol=0, pipette=p300, removalStepAfter=True): """ Similar to remove_supernatant, but the other way around. It transfers from point A to point B in <tipVol> ul trips and pours liquid from the top, to avoid contaminating the tip while transfering all the necessary volume. It also includes incubation and magnet """ protocol.comment( "\n\nADDING STEP: Transfering %s ul of %s to samples" % (vol, reagentName)) for index, ID in enumerate(columnID): src = reagent to = deepPlate[ID] currentip = availableTips.pop() retrieve_tip(p300, currentip) if (mixReagent == True) and ( index == 0 or index == 2 or index == 5 ): #If the reagent is to be mixed, and we are in column 1, 3 or 6, mix it. We mix three times to make sure we dont have differences protocol.comment("Mixing %s" % reagentName) well_mix( vol=beadsMixing, loc=beads, repsdown=0, repsmovement=beadsMixRepeats, yOffset=0, height=beadsHeight, moveSide=0 ) #We only do this with magnetic beads, that's why we use those variable names p300.blow_out(beads.top()) tvol = vol while tvol > tipVolume: p300.dispense(20, src.top()) p300.transfer(tipVolume, src.bottom().move( types.Point(x=0, y=0, z=bottomHeight)), to.top(topOffset), new_tip="never", air_gap=extraVol) protocol.delay(seconds=2) p300.blow_out() tvol -= tipVolume p300.dispense(20, src.top()) p300.transfer(tvol, src.bottom().move( types.Point(x=0, y=0, z=bottomHeight)), to.center(), new_tip="never", air_gap=extraVol) if (ID == "A2" or ID == "A4"): well_mix(vol=mixVol, loc=to, repsdown=downRepeats, repsmovement=movementRepeats, moveSide=-mixingOffset, height=altura) else: well_mix(vol=mixVol, loc=to, repsdown=downRepeats, repsmovement=movementRepeats, moveSide=mixingOffset, height=altura) if removalStepAfter == True: pipette.drop_tip(parkingRack[ID]) else: remove_tip(pipette, currentip) #Incubation if magnetTime == True: protocol.comment("Engaging magnet") magneto.engage(height=magnetHeight) protocol.comment("Incubating for %s minutes" % incubationTime) clock(time=incubationTime) ################# GO, VASILY, GO ################# ## ## ## ୧༼ಠ益ಠ༽୨ PROTOCOL ୧༼ಠ益ಠ༽୨ ## ## ## ################################################## magneto.disengage() #In case it is engaged from previous protocols. protocol.comment("We are working with column IDs: %s" % columnID) protocol.comment("\n\nSamples should have an initial volume of %s ul" % originalVol) #STEP 1: Add Proteinase K/LBF. slow_transfer(vol=proteinaseVol, reagent=proteinase, reagentName="Proteinase K/LBF", incubationTime=incubationProteinase, columnID=columnID, magnetTime=False, altura=SamplePlusProteinaseHeight, removalStepAfter=False, downRepeats=0, movementRepeats=20) #INCUBATION 1: 10 min [Total: 10 min] #STEP 2: mix magnetic beads, add them to samples and mix sample well. No slow_transfer function for the same reasons as before. protocol.comment("\n\nEnough incubation, time to do s t u f f") slow_transfer(vol=beadsVol, reagent=beads, reagentName="Magnetic beads", incubationTime=incubationBeadsNoMagnet, columnID=columnID, mixReagent=True, magnetTime=False, extraVol=10, altura=SamplePlusProteinasePlusBeadsHeight, downRepeats=0, movementRepeats=20) #INCUBATION 2: 5 min without magnet [Total: 15 min] protocol.comment( "Engaging magnet and keeping this incubation going for other %s minutes" % incubationBeadsMagnet) magneto.engage(height=magnetHeight) clock(time=incubationBeadsMagnet) #INCUBATION 3: 5 min incubation with magnet [Total: 20 min] #STEP 3: Remove magnetic beads supernatant remove_supernatant(vol=initialSupernatant + 20.5, wasteID="A1", reagentName="beads and proteinase", columnID=columnID) protocol.comment("Disengaging magnet") magneto.disengage() #STEP 4: Add 280 ul of Wash WBE slow_transfer(vol=washVol, reagent=WBE, reagentName="WBE", incubationTime=incubationWash, columnID=columnID) #INCUBATION 4: 3 min incubaton with magnet [Total: 23 min] #STEP 5: Removing WBE Supernatant remove_supernatant(vol=washVol, wasteID="A2", reagentName="WBE", columnID=columnID) protocol.comment("Disengaging magnet") magneto.disengage() #STEP 6: First wash with Eth, tips_transfer)anol slow_transfer(vol=washVol, reagent=ethanol1, reagentName="Ethanol 70% (First time)", incubationTime=incubationWash, columnID=columnID) #INCUBATION 5: 3 min incubaton with magnet [Total: 26 min] #STEP 7: Removing the supernatant of first wash with Ethanol remove_supernatant(vol=washVol, wasteID="A3", reagentName="Ethanol 70% (First time)", columnID=columnID) protocol.comment("Disengaging magnet") magneto.disengage() #STEP 8: Second wash with Ethanol slow_transfer(vol=washVol, reagent=ethanol2, reagentName="Ethanol 70% (Second time)", incubationTime=incubationWash, columnID=columnID) #INCUBATION 6: 3 min incubaton with magnet [Total: 26 min] #STEP 9: Removing the supernatant of second wash with Ethanol remove_supernatant(vol=washVol, wasteID="A4", reagentName="Ethanol 70% (Second time)", columnID=columnID) #INCUBATION 7: 5 min incubaton with magnet [Total: 31 min] protocol.comment( "This time, I do not disengage the magnet and let the beads dry for %s min" % str(incubationDry / 2)) clock(time=incubationDry / 2) remove_supernatant(vol=20, wasteID="A4", reagentName="Dried ethanol", columnID=columnID, newtip=True) protocol.comment( "Making sure I removed all the ethanol. Now incubating again for %s min" % str(incubationDry / 2)) clock(time=incubationDry / 2) #STEP 10: Diluting samples in 80 ul of RNAse free water protocol.comment("Disengaging magnet") magneto.disengage() protocol.comment("Diluting samples in %s ul of RNAse free water" % dilutionVol) slow_transfer(vol=dilutionVol, reagent=water, reagentName="RNAse-free water", incubationTime=incubationWater, columnID=columnID, mixVol=waterMixing, magnetTime=False, removalStepAfter=False) #Moving tip on top of pellet #INCUBATION 8: 5 min incubaton WITHOUT magnet [Total: 36 min] protocol.comment("Engaging magnet now!") magneto.engage(height=magnetHeight) clock(time=incubationWaterMagnet) #INCUBATION 9: 3 min incubaton WITH magnet [Total: 39 min] #STEP 11: Transfering samples to output plate protocol.comment( "Transfering DNA to output plate while magnet is still engaged") p300.flow_rate.aspirate = 20 for index, ID in enumerate(columnID): if (ID == "A2"): hahas = 1 else: hahas = -1 currentip = availableTips.pop() retrieve_tip(p300, currentip) src = deepPlate[ID] to = outplate[ID] p300.dispense(20, src.top()) p300.transfer(dilutionVol, src.bottom().move( types.Point(x=hahas, y=0, z=bottomHeight)), to.bottom(5), new_tip="never") protocol.delay(seconds=2) p300.dispense(20) remove_tip(p300, currentip) magneto.disengage() protocol.comment("\n\nFecho!")
def run(protocol: protocol_api.ProtocolContext): # LABWARE fuge_rack = protocol.load_labware('vwr_24_tuberack_1500ul', '1') stds_rack = protocol.load_labware('vwr_24_tuberack_1500ul', '2') tiprack300 = protocol.load_labware('opentrons_96_filtertiprack_200ul', '8') tiprack20 = protocol.load_labware('opentrons_96_filtertiprack_20ul', '9') tempdeck = protocol.load_module('tempdeck', '10') # plate = tempdeck.load_labware('amplifyt_96_aluminumblock_300ul') plate = tempdeck.load_labware('abi_96_wellplate_250ul') # PIPETTES p300 = protocol.load_instrument('p300_single_gen2', 'left', tip_racks=[tiprack300]) p20 = protocol.load_instrument('p20_single_gen2', 'right', tip_racks=[tiprack20]) # REAGENTS # sds_rack sN_mix = stds_rack['D1'] # empty; receives BPW_mix and water for stds std_1 = stds_rack['A3'] # 990ul Water std_2 = stds_rack['A4'] # 900ul water std_3 = stds_rack['A5'] # 900ul water std_4 = stds_rack['A6'] # 900ul water std_5 = stds_rack['B3'] # 900ul water std_6 = stds_rack['B4'] # 900ul water std_7 = stds_rack['B5'] # 900ul water water = stds_rack['B6'] # 1000ul water std_1mix = stds_rack['C3'] # empty std_2mix = stds_rack['C4'] # empty std_3mix = stds_rack['C5'] # empty std_4mix = stds_rack['C6'] # empty std_5mix = stds_rack['D3'] # empty std_6mix = stds_rack['D4'] # empty std_7mix = stds_rack['D5'] # empty NTC_mix = stds_rack['D6'] # empty, receives sN_mix and water as NTC #fuge_rack # bpwd_mix = fuge_rack['A1'] #empty # liquid_trash = fuge_rack['B1'] MIX_bw = fuge_rack['D1'] # see sheet, but gen around 1705 ul; use 2mL tube probe_10uM = fuge_rack['C1'] fwd_10uM = fuge_rack['C2'] # min 300ul rev_10uM = fuge_rack['D2'] # min 300ul tube_upp = fuge_rack['A4'] # e.g. 0.625uM # empty tube_mid = fuge_rack['A5'] # e.g. 1.25uM # empty tube_low = fuge_rack['A6'] # e.g. 2.5uM # empty probe_mix_1 = fuge_rack['C4'] # e.g. 0.625uM # empty probe_mix_2 = fuge_rack['C5'] # e.g. 1.25uM # empty probe_mix_3 = fuge_rack['C6'] # e.g. 2.5uM # empty probe_mix_4 = fuge_rack['D4'] # e.g. 5.0uM # empty probe_mix_5 = fuge_rack['D5'] # e.g. 7.5uM # empty probe_mix_6 = fuge_rack['D6'] # e.g. 10uM # empty # user inputs p300_max_vol = 200 orig_F_conc = 10 # What is the starting F primer concentration? (in uM) orig_R_conc = 10 # What is the starting R primer concentration? (in uM) orig_P_conc = 10 # What is probe starting concentration? (in uM) P_conc = 200 # What is the probe concentration for the stds? P_50 = 50 # Probe at lowest conc. P_100 = 100 # Probe at conc P_200 = 200 # Probe at conc P_400 = 400 # Probe at conc P_600 = 600 # Probe at conc P_800 = 800 # Probe at highest conc. sample_reps = 24 # How many samples at each F, R conc will be run? tot_stds = 21 # How many wells of standards will be run? (in # wells) tot_NTCs = 3 # How many wells of NTCs will be run? (in # wells) tot_samp = 72 # How many samples with varying conditions will be run? (in # wells) rxn_base = 8.86 # Everything in PCR buffer (Mg2+, dNTPs, polymerase, enhancers, stabilizers, sugars, etc.). (in uL) rxn_base_plus_water = 14.8 # This value set from other experiments. tot_rxn_vol = 20 # What is total volume of PCR reaction in plate/tube? (in ul) F_upp = 800 # F primer at highest concentration. (in nM) F_mid = 600 # What is the constant F primer concentration for standards? This should be guess or from literature or empirically determined. (in nM) F_low = 200 # F primer at concentration. (in nM) R_upp = 800 # R primer at lowest concentration. (in nM) R_mid = 600 # What is the constant R primer concentration for standards? This should be guess or from literature or empirically determined. (in nM) R_low = 200 # R primer at concentration. (in nM) dna_per_rxn = 2 # How much standard, positive control or NTC to add per well. std_NTC_reps = 3 # How many standard and NTC replicates? (int) P_reps = 12 # How many wells will use probe primer at particular concentration? (int) P_vol_rxn = 1.6 # What vol of probe will be added to reaction? (in ul) P_int_vol = 50 # What is the volume of F intermediate primer in new tube? (in ul) percent_waste = 0.2 # What percentage waste? (decimal) sN_mix_waste_offset = 0.05 # How much percent_waste offset should sN_mix use? This calculated as percent_waste-sN_mix_overage = percent_waste for sN_mix_overage e.g. (20-7=13%) Should not be 0 otherwise offset = percent_waste. (decimal) samp_int_mix_waste_offset = 0.05 # How much percent_waste offset should R_mix use? This calculated as percent_waste-R_mix_overage = percent_waste for R_mix_overage e.g. (20-=13%) If 0, then offset = percent_waste. (decimal) std_NTC_waste_offset = 0.07 # How much percent_waste offset should std_NTC use? (decimal) mix_samp_XFR_well_waste_offset = 0.08 #How much should offset be from each sample tube, upper, mid, low to the plate wells? Will receive P, be mixed and then aliquoted to 3 wells. # calcs tot_rxns = tot_stds + tot_NTCs + tot_samp # Calc what is total # rxns. (int) tot_stds_NTC = tot_stds + tot_NTCs # Calc number of standards and nontemplate controls. (int) rxn_vol_no_dna = tot_rxn_vol - dna_per_rxn # Calc what is volume of PCR rxn with no DNA added. (in ul) mix_bw_tot = rxn_base_plus_water * tot_rxns * ( 1 + percent_waste) # Tube with mix containing base and water. mix_bw_XFR_mix_sn = rxn_base_plus_water * tot_stds_NTC * ( 1 + percent_waste - sN_mix_waste_offset ) # Transfer this amount from MIX_bw to new tube to receive F, R, P for std and NTC prep std_vol_F_per_rxn = F_low / 1000 * tot_rxn_vol / orig_F_conc # Calc adding this much F primer to each std rxn std_vol_R_per_rxn = R_low / 1000 * tot_rxn_vol / orig_R_conc # Calc adding this much R primer to each std rxn std_vol_P_per_rxn = P_conc / 1000 * tot_rxn_vol / orig_P_conc # Calc adding this much Probe to each std rxn std_vol_water_per_rxn = 18 - ( rxn_base_plus_water + std_vol_F_per_rxn + std_vol_R_per_rxn + std_vol_P_per_rxn ) # How much water is added to the std_ntc reactions. Should be 18ul to receive 2ul DNA. (in ul) std_vol_F_mix = std_vol_F_per_rxn * tot_stds_NTC * ( 1 + percent_waste - sN_mix_waste_offset ) # How much F primer to add to MIX_sn? std_vol_R_mix = std_vol_R_per_rxn * tot_stds_NTC * ( 1 + percent_waste - sN_mix_waste_offset ) # How much R primer to add to MIX_sn? std_vol_P_mix = std_vol_P_per_rxn * tot_stds_NTC * ( 1 + percent_waste - sN_mix_waste_offset ) # How much P primer to add to MIX_sn? std_vol_water_mix = std_vol_water_per_rxn * tot_stds_NTC * ( 1 + percent_waste - sN_mix_waste_offset ) # How much water to add to MIX_sn? mix_sn_tot = mix_bw_XFR_mix_sn + std_vol_F_mix + std_vol_R_mix + std_vol_P_mix + std_vol_water_mix # Mix containing base+water+F,R,P. Needs to be aliquoted to std_int tubes mix_sn_XFR_to_std_int = std_NTC_reps * rxn_vol_no_dna * ( 1 + percent_waste - std_NTC_waste_offset ) # transfer this amount to std_int tubes std_dna_XFR_to_std_int = 6.72 #transfer this amount DNA to std_int_tubes to mix and aliquot to 3 wells dna_10x_dna_per_rxn = dna_per_rxn / 10 # Dilute DNA vol added by 10x and use std_4 instead of std_5 to save vol for P and F, R at upp mix_bw_XFR_samp_int = sample_reps * rxn_base_plus_water * ( 1 + percent_waste - samp_int_mix_waste_offset ) # transfer this amount from mix_bw to a new sample intermediate tube for diff values of F, R conc. Need to add 2ul from DNA dna_XFR_samp_int = sample_reps * dna_10x_dna_per_rxn * ( 1 + percent_waste - samp_int_mix_waste_offset ) # Add this DNA to a tube and mix before aliquoting to samp_int F_mid_rxn = F_mid / 1000 * tot_rxn_vol / orig_F_conc # How much F @ mid conc to add to rxn. F_mid_mix = F_mid_rxn * sample_reps * ( 1 + percent_waste - samp_int_mix_waste_offset ) # How much F to add to mix R_mid_rxn = R_mid / 1000 * tot_rxn_vol / orig_R_conc # How much R @ mid conc to add to rxn. R_mid_mix = R_mid_rxn * sample_reps * ( 1 + percent_waste - samp_int_mix_waste_offset ) # How much R to add to mix F_low_rxn = F_low / 1000 * tot_rxn_vol / orig_F_conc # How much F @ low conc to add to rxn. F_low_mix = F_low_rxn * sample_reps * ( 1 + percent_waste - samp_int_mix_waste_offset ) # How much F to add to mix R_low_rxn = R_low / 1000 * tot_rxn_vol / orig_R_conc # How much R @ low conc to add to rxn. R_low_mix = R_low_rxn * sample_reps * ( 1 + percent_waste - samp_int_mix_waste_offset ) # How much R to add to mix F_upp_rxn = F_upp / 1000 * tot_rxn_vol / orig_F_conc # How much F @ upp conc to add to rxn. F_upp_mix = F_upp_rxn * sample_reps * ( 1 + percent_waste - samp_int_mix_waste_offset ) # How much F to add to mix R_upp_rxn = R_upp / 1000 * tot_rxn_vol / orig_R_conc # How much R @ upp conc to add to rxn. R_upp_mix = R_upp_rxn * sample_reps * ( 1 + percent_waste - samp_int_mix_waste_offset ) # How much R to add to mix water_upp_rxn = tot_rxn_vol - (rxn_base_plus_water + dna_10x_dna_per_rxn + F_upp_rxn + R_upp_rxn + P_vol_rxn ) # How much water to add to upp rxn water_upp_mix = water_upp_rxn * sample_reps * ( 1 + percent_waste - samp_int_mix_waste_offset ) # How much water to add to upp mix water_low_rxn = 20 - (dna_10x_dna_per_rxn + F_low_rxn + R_low_rxn + rxn_base_plus_water + P_vol_rxn ) # How much water to add to low rxn water_low_mix = water_low_rxn * sample_reps * ( 1 + percent_waste - samp_int_mix_waste_offset ) # How much water to add to low mix water_mid_rxn = 20 - (rxn_base_plus_water + P_vol_rxn + dna_10x_dna_per_rxn + F_mid_rxn + R_mid_rxn ) # how much water to add to mid rxn water_mid_mix = water_mid_rxn * sample_reps * ( 1 + percent_waste - samp_int_mix_waste_offset ) # how much water to add to mid mix MIX_upp_samp_int = mix_bw_XFR_samp_int + dna_XFR_samp_int + F_upp_mix + R_upp_mix + water_upp_mix # How much in upper intermediate sample tube? MIX_mid_samp_int = mix_bw_XFR_samp_int + dna_XFR_samp_int + F_mid_mix + R_mid_mix + water_mid_mix # How much in middle intermediate sample tube? MIX_low_samp_int = mix_bw_XFR_samp_int + dna_XFR_samp_int + F_low_mix + R_low_mix + water_low_mix # How much in lower intermediate sample tube? mix_samp_XFR_to_well = 82.432 # How much to add to plate wells P_50_int_conc = P_50 / 1000 * tot_rxn_vol / P_vol_rxn # What intermediate (int) concentration of Probe is needed such that by adding 1.6ul I obtain a final concentration of 50, 100, 200…etc in rxn well? (in uM) P_100_int_conc = P_100 / 1000 * tot_rxn_vol / P_vol_rxn # What intermediate (int) concentration of Probe is needed such that by adding 1.6ul I obtain a final concentration of 50, 100, 200…etc in rxn well? (in uM) P_200_int_conc = P_200 / 1000 * tot_rxn_vol / P_vol_rxn # What intermediate (int) concentration of Probe is needed such that by adding 1.6ul I obtain a final concentration of 50, 100, 200…etc in rxn well? (in uM) P_400_int_conc = P_400 / 1000 * tot_rxn_vol / P_vol_rxn # What intermediate (int) concentration of Probe is needed such that by adding 1.6ul I obtain a final concentration of 50, 100, 200…etc in rxn well? (in uM) P_600_int_conc = P_600 / 1000 * tot_rxn_vol / P_vol_rxn # What intermediate (int) concentration of Probe is needed such that by adding 1.6ul I obtain a final concentration of 50, 100, 200…etc in rxn well? (in uM) P_800_int_conc = P_800 / 1000 * tot_rxn_vol / P_vol_rxn # What intermediate (int) concentration of Probe is needed such that by adding 1.6ul I obtain a final concentration of 50, 100, 200…etc in rxn well? (in uM) P_50_int_primer = P_50_int_conc * P_int_vol / orig_P_conc # What amount of primer should be added to generate int F primer conc? (in ul) P_100_int_primer = P_100_int_conc * P_int_vol / orig_P_conc # What amount of water should be added to generate int F primer conc? (in ul) P_200_int_primer = P_200_int_conc * P_int_vol / orig_P_conc # What amount of primer should be added to generate int F primer conc? (in ul) P_400_int_primer = P_400_int_conc * P_int_vol / orig_P_conc # What amount of water should be added to generate int F primer conc? (in ul) P_600_int_primer = P_600_int_conc * P_int_vol / orig_P_conc # What amount of primer should be added to generate int F primer conc? (in ul) P_800_int_primer = P_800_int_conc * P_int_vol / orig_P_conc # What amount of water should be added to generate int F primer conc? (in ul) P_50_int_water = P_int_vol - P_50_int_primer # What amount of primer should be added to generate int F primer conc? (in ul) P_100_int_water = P_int_vol - P_100_int_primer # What amount of water should be added to generate int F primer conc? (in ul) P_200_int_water = P_int_vol - P_200_int_primer # What amount of primer should be added to generate int F primer conc? (in ul) P_400_int_water = P_int_vol - P_400_int_primer # What amount of water should be added to generate int F primer conc? (in ul) P_600_int_water = P_int_vol - P_600_int_primer # What amount of primer should be added to generate int F primer conc? (in ul) P_800_int_water = P_int_vol - P_800_int_primer # What amount of water should be added to generate int F primer conc? (in ul) p_int_XFR_to_well = P_vol_rxn * 4 * ( 1 + percent_waste - mix_samp_XFR_well_waste_offset ) # What amount of probe intermediate to add to bolus in wells? #checks print("mix_bw_tot", mix_bw_tot) print("mix_bw_tot", mix_sn_tot) print("mix_bw_XFR_samp_int", mix_bw_XFR_samp_int) print("MIX_upp_samp_int", MIX_upp_samp_int) print("MIX_low_samp_int", MIX_low_samp_int) print("MIX_low_samp_int", MIX_low_samp_int) print("dna_XFR_samp_int", dna_XFR_samp_int) # lists # plate_col = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'] F_samp_vols = [F_upp_mix, F_mid_mix, F_low_mix] R_samp_vols = [R_upp_mix, R_mid_mix, R_low_mix] plate_rows = ['A', 'B', 'C', 'D', 'E', 'F'] # all_fwd = [fwd_1, fwd_2, fwd_3, fwd_4, fwd_5, fwd_6] std_tubes = [std_1, std_2, std_3, std_4, std_5, std_6, std_7, water] std_mixes = [ std_1mix, std_2mix, std_3mix, std_4mix, std_5mix, std_6mix, std_7mix, NTC_mix ] std_wells = ['G1', 'G4', 'G7', 'G10', 'H1', 'H4', 'H7', 'H10'] samp_tubes = [tube_upp, tube_mid, tube_low] probe_mixes = [ probe_mix_1, probe_mix_2, probe_mix_3, probe_mix_4, probe_mix_5, probe_mix_6 ] P_in_mix = [ P_50_int_primer, P_100_int_primer, P_200_int_primer, P_400_int_primer, P_600_int_primer, P_800_int_primer ] W_in_mix = [ P_50_int_water, P_100_int_water, P_200_int_water, P_400_int_water, P_600_int_water, P_800_int_water ] # #### COMMANDS ###### # prepare sN_mix # add MIX_bw to sN_mix tube p300.pick_up_tip() p300.flow_rate.aspirate = 92.86 #default p300.flow_rate.dispense = 92.86 #default MIX_bw_heights = tip_heights( mix_bw_tot, len(split_asp(mix_bw_XFR_mix_sn, p300_max_vol)), split_asp(mix_bw_XFR_mix_sn, p300_max_vol)[0]) p300.mix(3, 200, MIX_bw.bottom(MIX_bw_heights[0])) p300.flow_rate.aspirate = 40 #default p300.flow_rate.dispense = 40 #default for j in range(len(split_asp(mix_bw_XFR_mix_sn, p300_max_vol))): amt = split_asp(mix_bw_XFR_mix_sn, p300_max_vol)[j] p300.aspirate(amt, MIX_bw.bottom(MIX_bw_heights[j])) h = tip_heights(amt + amt * j, 1, 0)[0] p300.dispense(amt, sN_mix.bottom(h + 5)) p300.blow_out(sN_mix.bottom(20)) # want to be above liquid level p300.touch_tip() p300.drop_tip() # transfer water to sN__mix p300.flow_rate.aspirate = 40 #default p300.flow_rate.dispense = 40 #default p300.transfer( std_vol_water_mix, # 27.6ul water.bottom(20), sN_mix.bottom(tip_heights(mix_bw_XFR_mix_sn, 1, 0)[0]), blow_out=True, blowout_location='destination well') # transfer F primer @ std conditions to sN__mix p300.transfer( std_vol_F_mix, #22.08ul fwd_10uM.bottom(3), sN_mix.bottom(tip_heights(mix_bw_XFR_mix_sn, 1, 0)[0]), blow_out=True, mix_after=(2, 30), blowout_location='destination well') # transfer R primer @ std conditions to sN__mix p300.transfer( #some resid fluid on outside std_vol_R_mix, #22.08ul rev_10uM.bottom(3), sN_mix.bottom(tip_heights(mix_bw_XFR_mix_sn, 1, 0)[0]), blow_out=True, mix_after=(2, 30), blowout_location='destination well') # transfer Probe @ std conditions to sN__mix p20.flow_rate.aspirate = 4 p20.flow_rate.dispense = 4 p20.transfer( #some resid fluid on outside std_vol_P_mix, #16.56ul probe_10uM.bottom(3), sN_mix.bottom(tip_heights(mix_bw_XFR_mix_sn, 1, 0)[0]), blow_out=True, mix_after=(2, 20), blowout_location='destination well') p300.flow_rate.aspirate = 92.86 #default p300.flow_rate.dispense = 92.86 #default p20.flow_rate.aspirate = 7.56 p20.flow_rate.dispense = 7.56 # transfer sN_mix to intermediate tubes (std_mixes) std_mix_heights = tip_heights(mix_sn_tot, len(std_mixes), mix_sn_XFR_to_std_int) #[13,11,8,6,4,2,0] print(mix_bw_XFR_mix_sn) print(mix_sn_tot) print(std_mix_heights) p300.pick_up_tip() p300.mix(7, 200, sN_mix.bottom(std_mix_heights[0])) #10mm from bottom p300.flow_rate.aspirate = 30 p300.flow_rate.dispense = 40 # p300.well_bottom_clearance.aspirate = std_mix_heights[0] #mm for tube, h in zip(std_mixes, std_mix_heights): # p300.well_bottom_clearance.aspirate = h #mm p300.aspirate(mix_sn_XFR_to_std_int, sN_mix.bottom(h)) # 18 * 3 * 1.12-0.05= 54 + 6 =60ul protocol.delay(seconds=2) #tip equilibrate p300.move_to(sN_mix.bottom(35)) # excess tip fluid condense protocol.delay(seconds=3) #tip droplets slide p300.touch_tip() p300.dispense(mix_sn_XFR_to_std_int, tube) p300.drop_tip() p300.flow_rate.aspirate = 92.86 #reset to default p300.flow_rate.dispense = 92.86 #reset to default p300.well_bottom_clearance.aspirate = 10 #mm default # transfer std DNA into intermediate std_mixes tubes and then to plate for std, intTube, well in zip(std_tubes, std_mixes, std_wells): p20.pick_up_tip() p300.pick_up_tip() p20.flow_rate.aspirate = 4 p20.flow_rate.dispense = 4 p20.aspirate( std_dna_XFR_to_std_int, std ) #aspirate from std_1 into std_mix (intermediate tube) e.g. 6.42 ul protocol.delay(seconds=3) #equilibrate p20.touch_tip() p20.dispense(std_dna_XFR_to_std_int, intTube) # p20.move_to(intTube.bottom(3)) p20.flow_rate.aspirate = 7.56 p20.flow_rate.dispense = 7.56 p20.mix(2, 20, intTube.bottom(3)) #ensure vol in tip in intTube and washed p20.blow_out() p300.move_to( intTube.bottom(40)) #prevent tip from crashing into tube cap p300.mix(7, 50, intTube.bottom(1)) protocol.delay(seconds=2) # p300.move_to(intTube.bottom(10)) #prevent air bubbles in mmix during blow out p300.blow_out(intTube.bottom(10)) p20.move_to(intTube.bottom(40)) p20.flow_rate.aspirate = 4 p20.flow_rate.dispense = 4 for x in range(0, 3): # need int 1, 2, and 3 p20.aspirate(20, intTube) protocol.delay(seconds=2) #equilibrate # find digits in well, G1 and G10 and puts into list findNums = [int(i) for i in well.split()[0] if i.isdigit()] # joins nums from list [1, 0] -> 10 type = string colNum = ''.join(map(str, findNums)) # this finds row row = well.split()[0][0] dest = row + str(int(colNum) + x) # row + neighbor well i.e. 1, 2 p20.dispense(20, plate[dest].bottom(1)) p20.move_to(plate[dest].bottom(4)) p20.blow_out() # p20.touch_tip() p300.drop_tip() p20.drop_tip() p20.flow_rate.aspirate = 7.56 p20.flow_rate.dispense = 7.56 p20.well_bottom_clearance.dispense = 1 p20.well_bottom_clearance.aspirate = 1 # create samp_int tube mixes. sample intermediate # first add DNA from a std tube e.g. std_4 p300.transfer( dna_XFR_samp_int, # ~55.2 std_2.bottom(2), MIX_bw.bottom(tip_heights(mix_bw_tot - mix_bw_XFR_mix_sn, 1, 0)[0]), mix_after=(2, dna_XFR_samp_int), blow_out=True, blowout_location='destination well') # Three tubes created for upper, mid, lower F,R concentrations p300.pick_up_tip() p300.flow_rate.aspirate = 92.86 #default p300.flow_rate.dispense = 92.86 #default h = tip_heights(mix_bw_tot - mix_bw_XFR_mix_sn, len(split_asp(mix_bw_XFR_samp_int, p300_max_vol)), 408.48) #split_asp(mix_bw_XFR_samp_int, p300_max_vol)[0]) p300.mix(7, 200, MIX_bw.bottom(h[0] - 10)) # need to thoroughly mix DNA in tube for tube in samp_tubes: for j in range( len(split_asp(mix_bw_XFR_samp_int, p300_max_vol)) ): # split_asp is a function that returns equally divided aspirations p300.flow_rate.aspirate = 40 #default p300.flow_rate.dispense = 40 #default amt = split_asp(mix_bw_XFR_samp_int, p300_max_vol)[j] p300.aspirate(amt, MIX_bw.bottom(2)) protocol.delay(seconds=2) # h = tip_heights(amt+amt*j, 1, 0)[0] # adjust tip height depending on dispenses p300.dispense( amt, tube.bottom(3)) # want tip to be just a little above dispense p300.blow_out(tube.bottom(15)) # want to be above liquid level p300.touch_tip() p300.drop_tip() p300.well_bottom_clearance.aspirate = 1 #mm p300.well_bottom_clearance.dispense = 1 #mm # add F, R primers into samp_int tubes first with upper, mid (p300 vols), then with low (p20 vols) for i in range(2): h = tip_heights(mix_bw_XFR_samp_int, 1, 0)[0] p300.transfer(F_samp_vols[i], fwd_10uM.bottom(2), samp_tubes[i].bottom(h), mix_after=(2, 100), new_tip='always') p300.transfer(R_samp_vols[i], rev_10uM.bottom(2), samp_tubes[i].bottom(h), mix_after=(2, R_samp_vols[i]), new_tip='always') # F primer to low tube p20.transfer(F_samp_vols[-1], fwd_10uM.bottom(2), samp_tubes[-1].bottom( tip_heights(mix_bw_XFR_samp_int, 1, 0)[0]), mix_after=(2, F_samp_vols[-1]), new_tip='always') # R primer to low tube p20.transfer(R_samp_vols[-1], rev_10uM.bottom(2), samp_tubes[-1].bottom( tip_heights(mix_bw_XFR_samp_int, 1, 0)[0]), mix_after=(2, R_samp_vols[-1]), new_tip='always') # add water, dispense samp_int tubes containing F,R, water into plate # into each 1st well in plate, A1, B1..F1 then tube_mid into A5, B5..F5 for i, (tube, wvol) in enumerate( zip(samp_tubes, list([water_upp_mix, water_mid_mix, water_low_mix]))): p300.pick_up_tip() p300.flow_rate.aspirate = 40 #default p300.flow_rate.dispense = 40 #default p300.aspirate(wvol, water.bottom(10)) p300.dispense(wvol, tube.bottom(10)) p300.flow_rate.aspirate = 92.86 #default p300.flow_rate.dispense = 92.86 #default p300.mix(6, 200, tube.bottom(10)) for j, row in enumerate(plate_rows): h = tip_heights(MIX_upp_samp_int, len(plate_rows), mix_samp_XFR_to_well ) #3rd asp is low correct with small tot vol print(h) dest = row + str(4 * i + 1) p300.flow_rate.aspirate = 30 p300.flow_rate.dispense = 40 p300.aspirate(mix_samp_XFR_to_well, tube.bottom(h[j])) protocol.delay(seconds=2) # tip equilibrate p300.move_to(tube.bottom(25)) protocol.delay(seconds=2) p300.touch_tip( ) # bpwd_rxn*row reps (12) * waste = 16.8*12*(1+.12-0.05)= p300.dispense(mix_samp_XFR_to_well, plate[dest].bottom(1)) protocol.delay(seconds=1) p300.blow_out(plate[dest].bottom(10)) p300.touch_tip() p300.drop_tip() # now that PCR reactions are chillin' at 4C, make Probe int tubes # Mix 50ul 'probe' dilutions in tube by adding water and "probe" tube as shown in schedule # add water p300.pick_up_tip() p20.flow_rate.aspirate = 7.56 #default p20.flow_rate.dispense = 7.56 #default p300.flow_rate.aspirate = 92.86 #default p300.flow_rate.dispense = 92.86 #default for tube, wvol in zip(probe_mixes[0:4], W_in_mix[0:4]): # first 4 have vol > 20 p300.transfer( wvol, water.bottom(15), tube.bottom(1), blow_out=False, #this was creating air bubbles blowout_location='destination well', new_tip='never') p300.drop_tip() p20.pick_up_tip() # for tube, wvol in probe_mixes[4], W_in_mix[4]: # 5th item has vol < 20ul p20.transfer(W_in_mix[4], water.bottom(15), probe_mixes[4].bottom(1), blow_out=False, blowout_location='destination well', new_tip='never') p20.drop_tip() # add primer p20.pick_up_tip() for tube, pvol in zip(probe_mixes[0:3], P_in_mix[0:3]): # first three tubes have vol < 20ul p20.transfer(pvol, probe_10uM.bottom(2), tube.bottom(3), blow_out=False, mix_after=(2, pvol), blowout_location='destination well', new_tip='never') p20.drop_tip() # next tubes have vol > 20 p300.pick_up_tip() p300.flow_rate.aspirate = 20 #default p300.flow_rate.dispense = 40 #default for tube, pvol in zip(probe_mixes[3:], P_in_mix[3:]): # item 3 till end p300.transfer(pvol, probe_10uM.bottom(2), tube.bottom(2), blow_out=False, blowout_location='destination well', new_tip='never') p300.drop_tip() p300.flow_rate.aspirate = 92.86 #default p300.flow_rate.dispense = 92.86 #default p20.flow_rate.aspirate = 7.56 p20.flow_rate.dispense = 7.56 # Add probe to wells. mix, aliquot to adjacent wells P_mix_h = tip_heights(P_int_vol, 1, 0) for i, (tube, row) in enumerate(zip(probe_mixes, plate_rows)): p300.pick_up_tip() p20.pick_up_tip() p300.flow_rate.aspirate = 60 p300.flow_rate.dispense = 60 #don't want air bubbles p300.mix(3, 30, tube.bottom(P_mix_h[0])) # mix F primer tube, 100ul in tube p300.blow_out(tube.bottom(P_mix_h[0] + 6)) p300.touch_tip() for j in range(2): # asp and disp into wells p20.flow_rate.aspirate = 4 p20.flow_rate.dispense = 4 p20.move_to(tube.bottom(40)) if j == 0: # wells A1 and A5 dest = row + str(j + 1) nextWell = row + str(j + 5) p20.aspirate( p_int_XFR_to_well * 2, tube.bottom(2)) # ~7ul aspirate from P int tube to wells protocol.delay(seconds=2) p20.move_to( tube.bottom(2)) # relieve pressure if tip against tube p20.dispense(p_int_XFR_to_well, plate[dest].bottom(2)) protocol.delay(seconds=1) p20.touch_tip() p20.dispense(p_int_XFR_to_well, plate[nextWell].bottom(2)) protocol.delay(seconds=2) p20.blow_out(plate[nextWell].bottom(6)) p20.touch_tip() p20.drop_tip() p20.pick_up_tip() else: # well A9 dest = row + str(j + 8) p20.aspirate( p_int_XFR_to_well, tube.bottom(1)) # ~7ul aspirate from P int tube to wells p20.move_to( tube.bottom(2)) # relieve pressure if tip against tube protocol.delay(seconds=2) p20.touch_tip() p20.dispense(p_int_XFR_to_well, plate[dest]) protocol.delay(seconds=2) p20.blow_out(plate[dest].bottom(6)) p20.touch_tip() for k in range( 3): # need int 0, 1, 2. Looping through bolus in row (3) swell = row + str(4 * k + 1) #source well: A1, A5, A9 p300.move_to(plate[swell].bottom(30)) p300.flow_rate.aspirate = 92.86 p300.flow_rate.dispense = 92.86 p300.mix(3, 70, plate[swell].bottom(3)) p300.flow_rate.aspirate = 40 p300.flow_rate.dispense = 20 p300.mix(1, 70, plate[swell].bottom(2)) #slow mix to avoid/remove bubbles p300.blow_out(plate[swell].bottom(6)) for m in range(1, 4): # want int 1, 2, 3 p20.flow_rate.aspirate = 7.56 p20.flow_rate.dispense = 7.56 dwell = row + str( 4 * k + 1 + m) # loop through dispensing wells p20.move_to(plate[swell].bottom(40)) p20.aspirate(20, plate[swell].bottom(1)) protocol.delay(seconds=1) p20.dispense(20, plate[dwell].bottom(2)) protocol.delay(seconds=1) p20.move_to(plate[dwell].bottom(6)) p20.blow_out() p20.touch_tip() p20.drop_tip() p300.drop_tip()
def run(ctx: protocol_api.ProtocolContext): # Init protocol run run = ProtocolRun(ctx) minutos = 1 # Tendria que ser 60 pero para testeo lo pongo a 10 run.add_step(description="65C Incubation", wait_time=5 * minutos) # 5* 60 minutos 1 run.add_step(description="Transfer From temperature to magnet 485ul") # 2 run.add_step(description="Magnetic on: 10 minutes", wait_time=10 * minutos) # 10*60 3 run.add_step( description="Extraer liquido no beads. Slot 7 - Piscina Slot 3") # 4 run.add_step(description="Magnetic off") # 5 run.add_step( description= "Replace tips, add WB, add ETOH, vaciar piscina y trash. Cambiar nuevo DW SLOT 10" ) # INTERACTION 6 # Add WB run.add_step(description="Add 500ul de WB a los beats Slot 4 - 7 ") # 7 run.add_step(description="Magnetic on: 2 minutes", wait_time=2 * minutos) # 2*60 8 run.add_step(description="Extraer liquido no beats. Slot 7 - Slot 3") # 9 run.add_step(description="Magnetic off") # 10 # Add ETOH First step run.add_step(description="Add 500ul de etoh a los beats Slot 8 - 7 ") # 11 run.add_step(description="Magnetic on: 2 minutes", wait_time=2 * minutos) # 2*60 12 run.add_step(description="Extraer liquido no beats. Slot 7 - Slot 3") # 13 run.add_step(description="Magnetic off") # 14 run.add_step(description="Replace tips etc. add elution") # Add ETOH Second step run.add_step(description="Add 250ul de etoh a los beats Slot 8 - 7 ") # 15 run.add_step(description="Magnetic on: 2 minutes", wait_time=2 * minutos) # 2*60 16 run.add_step(description="Extraer liquido no beats. Slot 7 - Slot 3") # 17 run.add_step(description="Secar durante 10 minutos", wait_time=10) # 10 * 60 18 run.add_step(description="Magnetic off") # 19 run.add_step( description="Add elution move to temperature same tip 4 -> 7 -> 10" ) # 20 run.add_step(description="65C Incubation 10'", wait_time=10) # 10 * 60 # 21 run.add_step(description="Replace tips, change deepwell slot 7 magnet") run.add_step(description="Move 50ul from temp to magnet 10-7") # 22 run.add_step(description="Magnetic on: 3 minutes", wait_time=3 * minutos) #23 3 * 60 27 run.add_step(description="Move 50ul Magnet Final destination 7-> 2") # 24 run.add_step(description="Magnetic off") # 25 # execute avaliaible steps run.init_steps(steps) ################################## # Define desk moving_type = "axygen_96_wellplate_2000ul" moving_type_sim = "biorad_96_wellplate_200ul_pcr" # Destination plate SLOT 2 try: aw_slot = ctx.load_labware(moving_type, 2) except: moving_type = moving_type_sim aw_slot = ctx.load_labware(moving_type, 2) aw_wells = aw_slot.wells()[:NUM_SAMPLES] aw_wells_multi = aw_slot.rows()[0][:num_cols] wbeb_slot = ctx.load_labware('nest_12_reservoir_15mL', 4) wbeb_wells_multi = wbeb_slot.rows()[0][:num_cols] #Set up trash1 trash_pool_slot = ctx.load_labware('nest_1_reservoir_195ml', 3) trash_pool_wells_multi = trash_pool_slot.rows()[0][:num_cols] # # Magnetic module plus NEST_Deep_well_reservoire magdeck = ctx.load_module('magnetic module gen2', 7) magdeck.disengage() mag_slot = magdeck.load_labware(moving_type) mag_wells_multi = mag_slot.rows()[0][:num_cols] # Ethanol Pool etoh_slot = ctx.load_labware('nest_1_reservoir_195ml', 1) etoh_wells_multi = etoh_slot.rows()[0][:num_cols] # Temperature module plus NEST_Deep_well_reservoire tempdeck = ctx.load_module('tempdeck', 10) temp_slot = tempdeck.load_labware(moving_type) temp_wells_multi = temp_slot.rows()[0][:num_cols] # Mount pippets and set racks tips300_8 = ctx.load_labware('opentrons_96_filtertiprack_200ul', "8") tips300_9 = ctx.load_labware('opentrons_96_filtertiprack_200ul', "9") tips300_6 = ctx.load_labware('opentrons_96_filtertiprack_200ul', "6") tips300_5 = ctx.load_labware('opentrons_96_filtertiprack_200ul', "5") #run.mount_right_pip('p20_single_gen2', tip_racks=[tips20], capacity=20) run.mount_left_pip('p300_multi_gen2', tip_racks=[tips300_8, tips300_9, tips300_6, tips300_5], capacity=200, multi=True) run.set_pip("left") ############################################################################ # STEP 1: Incubation at 65ºC ############################################################################ if (run.next_step()): if (set_temp_on): tempdeck.set_temperature(temperature) run.finish_step() tempdeck.deactivate() ############################################################################ # STEP 2: Transfer From temperature to magnet 485ul ############################################################################ if (run.next_step()): run.set_pip("left") # p300 multi liquid = Reagent( name='MIX_HOT', num_wells=1, # change with num samples delay=0, flow_rate_aspirate=3, # Original 0.5 flow_rate_dispense=3, # Original 1 flow_rate_aspirate_mix=15, flow_rate_dispense_mix=25, reagent_reservoir_volume=485, h_cono=4, v_fondo=4 * math.pi * 4**3 / 3) air_gap_vol = 3 disposal_height = -5 pickup_height = 1 for source, destination in zip(temp_wells_multi, mag_wells_multi): run.pick_up() run.move_volume(reagent=liquid, source=source, dest=destination, vol=175, air_gap_vol=air_gap_vol, pickup_height=pickup_height, disp_height=disposal_height, rinse=True, touch_tip=True) run.move_volume(reagent=liquid, source=source, dest=destination, vol=175, air_gap_vol=air_gap_vol, pickup_height=pickup_height, disp_height=disposal_height, rinse=True, touch_tip=True) run.move_volume(reagent=liquid, source=source, dest=destination, vol=135, air_gap_vol=air_gap_vol, pickup_height=pickup_height, disp_height=disposal_height, rinse=True, touch_tip=True) run.drop_tip() run.finish_step() ############################################################################ # STEP 3: Magnet on 10 minutos ############################################################################ if (run.next_step()): if (set_mag_on): magdeck.engage(height=mag_height) run.finish_step() # Extraer liquido sin tocar los beats. Slot 7 - Piscina Slot 3 def move_magnet_to_trash(move_vol_steps=3): run.set_pip("left") # p300 multi # Sobre nadante primer paso liquid = Reagent( name='Sobrenadante', num_wells=1, # change with num samples delay=0, flow_rate_aspirate=0.2, # Original 0.5 flow_rate_dispense=3, # Original 1 reagent_reservoir_volume=528, h_cono=4, v_fondo=4 * math.pi * 4**3 / 3) air_gap_vol = 3 pickup_height = 1 disposal_height = 0 # Hay que revisar los offsets para el movimiento este for source in mag_wells_multi: destination = trash_pool_wells_multi[0] # Replace this run.pick_up() run.move_volume(reagent=liquid, source=source, dest=destination, vol=175, air_gap_vol=air_gap_vol, pickup_height=pickup_height, disp_height=disposal_height) # Patch for last step of etho 250ul instead of 500 if (move_vol_steps == 3): run.move_volume(reagent=liquid, source=source, dest=destination, vol=175, air_gap_vol=air_gap_vol, pickup_height=pickup_height, disp_height=disposal_height) # We want to empty does not matter if we aspirate more run.move_volume(reagent=liquid, source=source, dest=destination, vol=175, air_gap_vol=air_gap_vol, pickup_height=pickup_height, disp_height=disposal_height) run.drop_tip() ############################################################################ # STEP 4: Extract liquid from magnet to liquid trash ############################################################################ if (run.next_step()): move_magnet_to_trash() run.finish_step() ############################################################################ # STEP 5: Magnet off ############################################################################ if (run.next_step()): magdeck.disengage() run.finish_step() ############################################################################ # STEP 6: Pause to replace ############################################################################ if (run.next_step()): run.blink() ctx.pause( 'Replace tips, add WB, add ETOH, vaciar piscina y trash. Cambiar nuevo DW SLOT 10' ) run.reset_pip_count(run.get_current_pip()) run.finish_step() ############################################################################ # STEP 7: Add 500ul de WB a los bits 4 - 7 ############################################################################ if (run.next_step()): run.set_pip("left") # p300 multi vol_wb = 485 wb = Reagent( name='WB Wash buffer', flow_rate_aspirate=0.25, flow_rate_dispense=0.25, flow_rate_dispense_mix=0.25, flow_rate_aspirate_mix=0.25, delay=1, reagent_reservoir_volume=vol_wb * (NUM_SAMPLES + 1) * 1.1, h_cono=1.95, v_fondo=695, ) run.comment(wb.get_volumes_fill_print(), add_hash=True) wb.set_positions(wbeb_slot.rows()[0][0:wb.num_wells]) air_gap_vol = 3 disposal_height = -1 # Arriba y el último paso lo hacemos dentro pool_area = 8.3 * 71.1 for destination in mag_wells_multi: run.pick_up() pickup_height = wb.calc_height(pool_area, 175 * 8) run.move_volume(reagent=liquid, source=wb.get_current_position(), dest=destination, vol=175, air_gap_vol=air_gap_vol, pickup_height=pickup_height, disp_height=disposal_height) pickup_height = wb.calc_height(pool_area, 175 * 8) run.move_volume(reagent=liquid, source=wb.get_current_position(), dest=destination, vol=175, air_gap_vol=air_gap_vol, pickup_height=pickup_height, disp_height=disposal_height) # This will be drop inside pickup_height = wb.calc_height(pool_area, 175 * 8) disposal_height = 2 run.move_volume(reagent=liquid, source=wb.get_current_position(), dest=destination, vol=135, air_gap_vol=air_gap_vol, pickup_height=pickup_height, disp_height=disposal_height - 3) run.custom_mix(liquid, location=destination, vol=50, rounds=10, blow_out=True, mix_height=0) run.drop_tip() run.finish_step() ############################################################################ # STEP 8: Magnet on 2 minutos ############################################################################ if (run.next_step()): if (set_mag_on): magdeck.engage(height=mag_height) run.finish_step() ############################################################################ # STEP 9: Extract liquid from magnet to liquid trash ############################################################################ if (run.next_step()): move_magnet_to_trash() run.finish_step() ############################################################################ # STEP 10: Magnet off ############################################################################ if (run.next_step()): magdeck.disengage() run.finish_step() # Used twice in the next steps vol_etoh = 500 + 250 etoh = Reagent(name='ETOH', flow_rate_aspirate=1, flow_rate_dispense=1, flow_rate_dispense_mix=4, flow_rate_aspirate_mix=4, delay=1, reagent_reservoir_volume=vol_etoh * (NUM_SAMPLES + 1), vol_well_max=195000, rinse=True, num_wells=1, h_cono=1.95, v_fondo=695) run.comment(etoh.get_volumes_fill_print(), add_hash=True) ############################################################################ # STEP 11: Add 500ul de etoh a los beats Slot 8 - 7 ############################################################################ if (run.next_step()): run.set_pip("left") # p300 multi liquid = etoh air_gap_vol = 3 disposal_height = -1 # Arriba y el último paso lo hacemos dentro pickup_height = 1 for source, destination in zip(etoh_wells_multi, mag_wells_multi): run.pick_up() run.move_volume(reagent=liquid, source=source, dest=destination, vol=175, air_gap_vol=air_gap_vol, pickup_height=pickup_height, disp_height=disposal_height) run.move_volume(reagent=liquid, source=source, dest=destination, vol=175, air_gap_vol=air_gap_vol, pickup_height=pickup_height, disp_height=disposal_height) # This will be drop inside run.move_volume(reagent=liquid, source=source, dest=destination, vol=135, air_gap_vol=air_gap_vol, pickup_height=pickup_height, disp_height=disposal_height - 3) run.custom_mix(liquid, location=destination, vol=50, rounds=5, blow_out=True, mix_height=0) run.drop_tip() run.finish_step() ############################################################################ # STEP 12: Magnet on 10 minutos ############################################################################ if (run.next_step()): if (set_mag_on): magdeck.engage(height=mag_height) run.finish_step() ############################################################################ # STEP 13: Extract liquid from magnet to liquid trash ############################################################################ if (run.next_step()): move_magnet_to_trash() run.finish_step() ############################################################################ # STEP 14 : Magnet off ############################################################################ if (run.next_step()): magdeck.disengage() run.finish_step() ############################################################################ # STEP 15: Run pause ############################################################################ if (run.next_step()): run.blink() ctx.pause('Replace tips,add elution') run.reset_pip_count(run.get_current_pip()) run.finish_step() ############################################################################ # STEP 16: Add 250 de etoh a los beats Slot 8 - 7 ############################################################################ if (run.next_step()): run.set_pip("left") # p300 multi liquid = etoh air_gap_vol = 3 disposal_height = -1 # Arriba y el último paso lo hacemos dentro pickup_height = 1 for source, destination in zip(etoh_wells_multi, mag_wells_multi): run.pick_up() run.move_volume(reagent=liquid, source=source, dest=destination, vol=175, air_gap_vol=air_gap_vol, pickup_height=pickup_height, disp_height=disposal_height) # This will be drop inside run.move_volume(reagent=liquid, source=source, dest=destination, vol=125, air_gap_vol=air_gap_vol, pickup_height=pickup_height, disp_height=disposal_height - 3) run.custom_mix(liquid, location=destination, vol=50, rounds=5, blow_out=True, mix_height=0) run.drop_tip() ############################################################################ # STEP 17: Magnet on 2 minutos ############################################################################ if (run.next_step()): if (set_mag_on): magdeck.engage(height=mag_height) run.finish_step() ############################################################################ # STEP 18: Extract liquid from magnet to liquid trash ############################################################################ if (run.next_step()): move_magnet_to_trash(move_vol_steps=2) run.finish_step() ############################################################################ # STEP 19: Secar durante 10 minutos ############################################################################ if (run.next_step()): run.finish_step() run.blink() ctx.pause('Revisa que esté seco') ############################################################################ # STEP 20: Magnet off ############################################################################ if (run.next_step()): magdeck.disengage() run.finish_step() ############################################################################ # STEP 21: Add elution move to temperature same tip 4 -> 7 -> 10 ############################################################################ # Used to move from temp to magnet and from magnet to destionation elu_beads = Reagent( name='BeatsToHot', num_wells=1, # change with num samples delay=0, flow_rate_aspirate=3, # Original 0.5 flow_rate_dispense=3, # Original 1 flow_rate_aspirate_mix=15, flow_rate_dispense_mix=25, reagent_reservoir_volume=528, h_cono=4, v_fondo=4 * math.pi * 4**3 / 3) if (run.next_step()): # to liquid types vol_eb = 50 elution = Reagent(name='Elution Buffer', flow_rate_aspirate=2, flow_rate_dispense=2, flow_rate_dispense_mix=4, flow_rate_aspirate_mix=4, reagent_reservoir_volume=vol_eb * (NUM_SAMPLES + 1), delay=1, num_wells=1, h_cono=1.95, v_fondo=695, rinse_loops=3) run.comment(elution.get_volumes_fill_print(), add_hash=True) elution.set_positions(wbeb_slot.rows()[0][11:12]) air_gap_vol = 3 disposal_height = -5 pickup_height = 1 for dest_source, destination in zip(mag_wells_multi, temp_wells_multi): run.pick_up() run.move_volume(reagent=elution, source=elution.get_current_position(), dest=dest_source, vol=vol_eb, air_gap_vol=air_gap_vol, pickup_height=pickup_height, disp_height=disposal_height) run.custom_mix(elu_beads, location=dest_source, vol=100, rounds=10, blow_out=True, mix_height=0) # This will be drop inside run.move_volume(reagent=elu_beads, source=dest_source, dest=destination, vol=50, air_gap_vol=air_gap_vol, pickup_height=pickup_height, disp_height=disposal_height - 3) run.drop_tip() run.finish_step() ############################################################################ # STEP 22: Incubation at 65ºC ############################################################################ if (run.next_step()): if (set_temp_on): tempdeck.set_temperature(temperature) run.finish_step() ############################################################################ # STEP 23: Pause to reset tips, replace deep well SLOT 7 and add DeepWell on SLOT2 ############################################################################ if (run.next_step()): run.blink() ctx.pause( 'Replace tips, change DeepWell on Magnet SLOT 7, and add final Deepwell on SLOT 2' ) run.reset_pip_count(run.get_current_pip()) run.finish_step() ############################################################################ # STEP 24: Move from temp to magnet ############################################################################ if (run.next_step()): result = Reagent( name='Elution+magnets', num_wells=1, # change with num samples delay=0, flow_rate_aspirate=3, # Original 0.5 flow_rate_dispense=3, # Original 1 flow_rate_aspirate_mix=15, flow_rate_dispense_mix=25, reagent_reservoir_volume=528, h_cono=4, v_fondo=4 * math.pi * 4**3 / 3) for source, destination in zip(temp_wells_multi, mag_wells_multi): run.pick_up() run.move_volume(reagent=result, source=source, dest=destination, vol=1, air_gap_vol=air_gap_vol, pickup_height=pickup_height, disp_height=disposal_height) run.drop_tip() run.finish_step() ############################################################################ # STEP 25: Magnet on 3 minutos ############################################################################ if (run.next_step()): if (set_mag_on): magdeck.engage(height=mag_height) run.finish_step() ############################################################################ # STEP 26: Move from magnet to final output slot 2 ############################################################################ if (run.next_step()): result = Reagent( name='Elution-magnets', num_wells=1, # change with num samples delay=0, flow_rate_aspirate=3, # Original 0.5 flow_rate_dispense=3, # Original 1 flow_rate_aspirate_mix=15, flow_rate_dispense_mix=25, reagent_reservoir_volume=528, h_cono=4, v_fondo=4 * math.pi * 4**3 / 3) for source, destination in zip(mag_wells_multi, aw_wells_multi): run.pick_up() run.move_volume(reagent=result, source=source, dest=destination, vol=50, air_gap_vol=air_gap_vol, pickup_height=pickup_height, disp_height=disposal_height) run.drop_tip() run.finish_step() ############################################################################ # STEP 27: Magnet off ############################################################################ if (run.next_step()): magdeck.disengage() run.finish_step() run.log_steps_time() run.blink() ctx.comment('Finished! \nMove plate to PCR')
def run(protocol: protocol_api.ProtocolContext): # LABWARE fuge_rack = protocol.load_labware( 'opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap', '2') tiprack300 = protocol.load_labware('opentrons_96_filtertiprack_200ul', '8') tiprack20 = protocol.load_labware('opentrons_96_filtertiprack_20ul', '9') tempdeck = protocol.load_module( 'tempdeck', '10') # leaving on so I don't have to move off plate = protocol.load_labware('corning_96_wellplate_360ul_flat', '3') reagent_rack = protocol.load_labware( 'opentrons_6_tuberack_nest_50ml_conical', '6') # PIPETTES p300 = protocol.load_instrument('p300_single_gen2', 'left', tip_racks=[tiprack300]) p20 = protocol.load_instrument('p20_single_gen2', 'right', tip_racks=[tiprack20]) # REAGENTS #reagent_rack luminaseBuffer = reagent_rack[ 'B1'] #Raquel's V2 mix form 22 April 2021; 19536ul std_1 = fuge_rack['A1'] # 900ul Water std_2 = fuge_rack['A2'] # 900ul water std_3 = fuge_rack['A3'] # 900ul water std_4 = fuge_rack['A4'] # 900ul water std_5 = fuge_rack['A5'] # 900ul water std_6 = fuge_rack['A6'] # 900ul water std_7 = fuge_rack['B1'] # 900ul water std_8 = fuge_rack['B2'] # 900ul water std_9 = fuge_rack['B3'] # 900ul water std_10 = fuge_rack['B4'] # 900ul water std_11 = fuge_rack['B5'] # 900ul water std_12 = fuge_rack['B6'] # 900ul water std_13 = fuge_rack['C1'] # 900ul water std_14 = fuge_rack['C2'] # 900ul water std_15 = fuge_rack['C3'] # 900ul water water = fuge_rack['D6'] trash = fuge_rack['C6'] # trash; receives some of the blowouts # lists dATP_vol = 15 luminaseBuffer_vol = 185 rows = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'] std_wells = [ std_1, std_2, std_3, std_4, std_5, std_6, std_7, std_8, std_9, std_10, std_11, std_12, std_13, std_14, std_15, water ] #### COMMANDS ###### # Add luminase buffer containing D-luciferin, reagent and water p300.pick_up_tip() sample_h = fifty_ml_heights(19536, 96, 185) # volumes are different, so take median sample_counter = 0 for j in range(12): # cols 1..10 can be serviced by p200. for row in rows: # process 8 rows dest = row + str(j + 1) p300.aspirate(luminaseBuffer_vol, luminaseBuffer.bottom(sample_h[sample_counter])) p300.dispense(luminaseBuffer_vol, plate[dest].bottom(5)) p300.blow_out(plate[dest].bottom(5)) p300.move_to(plate[dest].bottom()) p300.drop_tip() protocol.pause( 'All reagents added but ATP for background calculations. Resume to add ATP.' ) # add ATP serial dilutions p300.pick_up_tip() dATP_bolus = 5 for j, (tube, row) in enumerate( zip(reversed(std_wells), reversed(2 * rows)) ): #forgive me; loop in reverse; keep tip for speed so low conc to high conc p300.aspirate(dATP_vol * 6 + dATP_bolus, tube.bottom(20)) #5ul bolus for i in range(6): # process 6 rows dest = row + str(i + 7) if j < 8 else row + str( i + 1) # going backwards, need to move to 1st half p300.dispense(dATP_vol, plate[dest].bottom(2)) p300.dispense(dATP_bolus, trash.top(-4)) # remove bolus p300.blow_out(trash.top(-4)) p300.touch_tip(trash, v_offset=-4) p300.drop_tip()
def _simulate(self): self._reset() stack = [] res = [] commands = [] self._containers.clear() self._instruments.clear() self._modules.clear() self._interactions.clear() def on_command(message): payload = message['payload'] description = payload.get('text', '').format( **payload ) if message['$'] == 'before': level = len(stack) stack.append(message) commands.append(payload) res.append( { 'level': level, 'description': description, 'id': len(res)}) else: stack.pop() unsubscribe = self._broker.subscribe(command_types.COMMAND, on_command) try: # ensure actual pipettes are cached before driver is disconnected if ff.use_protocol_api_v2(): self._hardware.cache_instruments() instrs = {} for mount, pip in self._hardware.attached_instruments.items(): if pip: instrs[mount] = {'model': pip['model'], 'id': pip.get('pipette_id', '')} sim = adapters.SynchronousAdapter.build( API.build_hardware_simulator, instrs, [mod.name() for mod in self._hardware.attached_modules.values()], strict_attached_instruments=False) sim.home() self._simulating_ctx = ProtocolContext(self._loop, sim, self._broker) if self._is_json_protocol: run_protocol(protocol_json=self._protocol, simulate=True, context=self._simulating_ctx) else: run_protocol(protocol_code=self._protocol, simulate=True, context=self._simulating_ctx) else: self._hardware.broker = self._broker self._hardware.cache_instrument_models() self._hardware.disconnect() if self._is_json_protocol: execute_protocol(self._protocol) else: exec(self._protocol, {}) finally: # physically attached pipettes are re-cached during robot.connect() # which is important, because during a simulation, the robot could # think that it holds a pipette model that it actually does not if not ff.use_protocol_api_v2(): self._hardware.connect() unsubscribe() instruments, containers, modules, interactions = _accumulate( [_get_labware(command) for command in commands]) self._containers.extend(_dedupe(containers)) self._instruments.extend(_dedupe(instruments)) self._modules.extend(_dedupe(modules)) self._interactions.extend(_dedupe(interactions)) # Labware calibration happens after simulation and before run, so # we have to clear the tips if they are left on after simulation # to ensure that the instruments are in the expected state at the # beginning of the labware calibration flow if not ff.use_protocol_api_v2(): self._hardware.clear_tips() return res
def run(protocol: protocol_api.ProtocolContext): ####################################################################################################################################### ## SETUP # Load Labware temp_mod = protocol.load_module('Temperature Module', '9') reaction_plate = protocol.load_labware( "biorad_384_wellplate_50ul", "8", label="reaction plate") # where the magic happens # tube_rack = protocol.load_labware("opentrons_96_aluminumblock_generic_pcr_strip_200ul", "6", label = "aluminum block") # CBS and substrate stocks sample_plate = protocol.load_labware( "greiner_96_wellplate_323ul", "6", label="sample plate" ) # CBS and dye stocks (!!! protect dye from light !!!) library_plate = protocol.load_labware( "greiner_96_wellplate_323ul", "5", label="library plate") # compound library # Specify tip racks tiprack1 = protocol.load_labware("opentrons_96_tiprack_10ul", '2') tiprack2 = protocol.load_labware("opentrons_96_tiprack_300ul", '3') # Load pipettes and set parameters p10 = protocol.load_instrument("p10_multi", "right", tip_racks=[tiprack1]) p50 = protocol.load_instrument('p50_multi', "left", tip_racks=[tiprack2]) p10.flow_rate.aspirate = 8 p10.flow_rate.dispense = 8 # 384-well depth is 11.56 mm and max volume is 112 uL # 20 uL is 2 mm high, tandem (middle) wall is 5.1 mm high p10.well_bottom_clearance.dispense = 1 p50.well_bottom_clearance.dispense = 7 # Specify target wells (ONLY NEED TO EDIT WELLS HERE) samples = ["5", "6"] # columns on sample plate with protein and dye cols_compounds = [6, 7, 8, 9, 10] # library columns to aspirate compounds from cols_woSAM = [1, 2, 3, 4, 5] # destination wells in reaction plate (384-tandem) cols_wSAM = [ 6, 7, 8, 9, 10 ] # destination wells in reaction plate (384-tandem) (30 uM SAM final c) wells_reaction_woSAM = ['A' + str(i) for i in cols_woSAM] wells_reaction_wSAM = ['A' + str(i) for i in cols_wSAM] wells_reaction = ['A' + str(i) for i in (cols_woSAM + cols_wSAM)] ####################################################################################################################################### ## PROCEDURE # Distribute fluorescent dye from sample plate to reaction plate # p10.distribute(5, sample_plate.columns_by_name()[samples[2]], [reaction_plate.wells_by_name()[i] for i in wells_reaction], # disposal_volume = 0, blow_out = False, touch_tip = True) # Distribute protein mixed with fluorescent dye p10.distribute( 13.5, sample_plate.columns_by_name()[samples[0]], [reaction_plate.wells_by_name()[i] for i in wells_reaction_woSAM], disposal_volume=0, blow_out=False, new_tip='once') p10.distribute( 13.5, sample_plate.columns_by_name()[samples[1]], [reaction_plate.wells_by_name()[i] for i in wells_reaction_wSAM], disposal_volume=0, blow_out=False, new_tip='once') #p10.distribute(13.5, sample_plate.columns_by_name()[samples[1]], [reaction_plate.wells_by_name()[i] for i in wells_reaction_wSAM], #disposal_volume = 0, blow_out = False, new_tip = 'once', touch_tip = True) # Distribute compounds from 96-well library plate and mix vol = 1.5 for i in range(0, len(cols_compounds)): p10.transfer(vol, library_plate.columns_by_name()[str(cols_compounds[i])], reaction_plate.wells_by_name()[wells_reaction_woSAM[i]], mix_after=(3, vol)) p10.transfer(vol, library_plate.columns_by_name()[str(cols_compounds[i])], reaction_plate.wells_by_name()[wells_reaction_wSAM[i]], mix_after=(3, vol))
def run(ctx: protocol_api.ProtocolContext): # load labware ic_pk = ctx.load_labware( 'opentrons_24_aluminumblock_nest_2ml_snapcap', '9', 'chilled tubeblock for internal control and proteinase K (strip 1)' ).wells()[0] source_racks = [ ctx.load_labware( 'opentrons_24_tuberack_eppendorf_2ml_safelock_snapcap', slot, 'source tuberack ' + str(i + 1)) for i, slot in enumerate(['1', '2', '3', '4']) ] dest_plate = ctx.load_labware('nest_96_wellplate_2ml_deep', '8', '96-deepwell sample plate') binding_buffer = ctx.load_labware( 'opentrons_6_tuberack_falcon_50ml_conical', '11', '50ml tuberack for binding buffer (tube B1)').wells()[1] # binding_buffer = ctx.load_labware( # 'biorad_96_wellplate_200ul_pcr', '11', # '50ml tuberack for lysis buffer + PK (tube A1)').wells()[1] tipracks1000 = [ ctx.load_labware('opentrons_96_filtertiprack_1000ul', slot, '1000µl filter tiprack') for slot in ['10', '7'] ] tipracks20 = [ ctx.load_labware('opentrons_96_filtertiprack_20ul', '6', '20µl filter tiprack') ] # load pipette s20 = ctx.load_instrument('p20_single_gen2', 'left', tip_racks=tipracks20) p1000 = ctx.load_instrument('p1000_single_gen2', 'right', tip_racks=tipracks1000) # setup samples sources = [well for rack in source_racks for well in rack.wells()][:NUM_SAMPLES] dests_single = dest_plate.wells()[:NUM_SAMPLES] num_cols = math.ceil(NUM_SAMPLES / 8) dests_multi = dest_plate.rows()[0][:num_cols] tip_log = {'count': {}} folder_path = '/data/A' tip_file_path = folder_path + '/tip_log.json' if TIP_TRACK and not ctx.is_simulating(): if os.path.isfile(tip_file_path): with open(tip_file_path) as json_file: data = json.load(json_file) if 'tips1000' in data: tip_log['count'][p1000] = data['tips1000'] else: tip_log['count'][p1000] = 0 if 'tips20' in data: tip_log['count'][s20] = data['tips20'] else: tip_log['count'][s20] = 0 else: tip_log['count'] = {p1000: 0, s20: 0} tip_log['tips'] = { p1000: [tip for rack in tipracks1000 for tip in rack.wells()], #s20: [tip for rack in tipracks20 for tip in rack.rows()[0]] s20: [tip for rack in tipracks20 for tip in rack.wells()] } tip_log['max'] = {pip: len(tip_log['tips'][pip]) for pip in [p1000, s20]} def pick_up(pip): nonlocal tip_log if tip_log['count'][pip] == tip_log['max'][pip]: ctx.pause('Replace ' + str(pip.max_volume) + 'µl tipracks before \ resuming.') pip.reset_tipracks() tip_log['count'][pip] = 0 pip.pick_up_tip(tip_log['tips'][pip][tip_log['count'][pip]]) tip_log['count'][pip] += 1 heights = {binding_buffer: TUBE50_VOlUME * 1} radius = (binding_buffer.diameter) / 2 min_h = 5 def h_track(vol, tube): nonlocal heights dh = vol / (math.pi * (radius**2)) if heights[tube] - dh > min_h: heights[tube] = heights[tube] - dh else: heights[tube] = min_h # stop 5mm short of the bottom return heights[tube] p1000.flow_rate.aspirate = 50 p1000.flow_rate.dispense = 60 p1000.flow_rate.blow_out = 100 # transfer internal control + proteinase K pick_up(s20) for d in dests_single: s20.dispense(10, ic_pk.bottom(2)) s20.transfer(ICPK_VOlUME, ic_pk.bottom(2), d.bottom(2), air_gap=5, new_tip='never') s20.air_gap(5) s20.drop_tip() # # transfer binding buffer and mix # pick_up(p1000) # for i, (s, d) in enumerate(zip(sources, dests_single)): # # source = binding_buffer[i//96] # 1 tube of binding buffer can accommodate all samples here # h = h_track(275, source) # # custom mix # p1000.flow_rate.aspirate = 100 # p1000.flow_rate.dispense = 100 # p1000.dispense(500, source.bottom(h+20)) # for _ in range(4): # # p1000.air_gap(500) # p1000.aspirate(500, source.bottom(h)) # p1000.dispense(500, source.bottom(h+20)) pick_up(p1000) for i in range(math.ceil(NUM_SAMPLES / 2)): if NUM_SAMPLES % 2 != 0 and i == math.ceil(NUM_SAMPLES / 2) - 1: dest_set = [dest_plate.wells()[NUM_SAMPLES - 1]] else: dest_set = dest_plate.wells()[i * 2:i * 2 + 2] for i in range(len(dest_set)): h = h_track(BB_VOLUME, binding_buffer) if i == 0: p1000.mix(MIX_REPETITIONS, MIX_VOLUME, binding_buffer.bottom(h)) p1000.aspirate(BB_VOLUME, binding_buffer.bottom(h)) p1000.air_gap(20) for s in dest_set: p1000.dispense(BB_VOLUME + 20, s) p1000.drop_tip() ctx.comment('Move deepwell plate (slot 4) to Station B for RNA \ extraction.') # track final used tip if not ctx.is_simulating(): if not os.path.isdir(folder_path): os.mkdir(folder_path) data = { 'tips1000': tip_log['count'][p1000], 'tips20': tip_log['count'][s20] } with open(tip_file_path, 'w') as outfile: json.dump(data, outfile)
def run(protocol: protocol_api.ProtocolContext): # LABWARE tiprack300 = protocol.load_labware('opentrons_96_filtertiprack_200ul', '8') # tiprack20 = protocol.load_labware('opentrons_96_filtertiprack_20ul', '9') sectempdeck = protocol.load_module('tempdeck', '10') fuge_rack = sectempdeck.load_labware( # 'opentrons_24_aluminumblock_generic_2ml_screwcap') 'opentrons_24_aluminumblock_nest_1.5ml_screwcap') holder_1 = protocol.load_labware( '8wstriptubesonfilterracks_96_aluminumblock_250ul', '3') holder_2 = protocol.load_labware( '8wstriptubesonfilterracks_96_aluminumblock_250ul', '6') # PIPETTES p300 = protocol.load_instrument('p300_single_gen2', 'left', tip_racks=[tiprack300]) # p20 = protocol.load_instrument( # 'p20_single_gen2', 'right', tip_racks=[tiprack20] # ) # REAGENTS a_std_1 = fuge_rack['A1'] # 980ul Water + 20ul Already prepared a_std_2 = fuge_rack['A2'] # 750ul water a_std_3 = fuge_rack['A3'] # 750ul water a_std_4 = fuge_rack['A4'] # 750ul water a_std_5 = fuge_rack['A5'] # 750ul water a_std_6 = fuge_rack['A6'] # 750ul water a_std_7 = fuge_rack['D1'] # 750ul water a_std_8 = fuge_rack['D2'] # 750ul water a_std_9 = fuge_rack['D3'] # 750ul water a_std_10 = fuge_rack['D4'] # 750ul water a_std_11 = fuge_rack['D5'] # 750ul water a_std_12 = fuge_rack['D6'] # 750ul water # LISTS stds = [ a_std_1, a_std_2, a_std_3, a_std_4, a_std_5, a_std_6, a_std_7, a_std_8, a_std_9, a_std_10, a_std_11, a_std_12 ] stds_to_add_to_PCR_tubes = [ a_std_3, a_std_4, a_std_5, a_std_6, a_std_7, a_std_8, a_std_9, a_std_10 ] num_of_sample_reps_per_holder = 6 # can't exceed 6 holderList = [holder_1, holder_2] SAMP_wells = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'] #### COMMANDS ###### # Make std dilution series for i in range(len(stds) - 1): p300.pick_up_tip() p300.mix(2, 200, stds[i].bottom(4)) # mix low p300.mix(2, 200, stds[i].bottom(8)) # mix mid p300.mix(5, 200, stds[i].bottom(16)) # mix hi p300.aspirate(125, stds[i].bottom(8)) # 2*150 = 250 p300.touch_tip(v_offset=-3) p300.dispense(125, stds[i + 1].bottom(8)) p300.mix(2, 125, stds[i + 1].bottom(8)) # wash tip p300.blow_out(stds[i + 1].bottom(16)) # blow out just below the surface p300.touch_tip(v_offset=-3) p300.aspirate(125, stds[i].bottom(8)) p300.touch_tip(v_offset=-3) p300.dispense(125, stds[i + 1].bottom(8)) p300.mix(2, 125, stds[i + 1].bottom(8)) # wash tip p300.blow_out(stds[i + 1].bottom(16)) # blow out just below the surface p300.touch_tip(v_offset=-3) p300.drop_tip() if i == len(stds) - 2: # last tube p300.pick_up_tip() p300.mix(2, 200, stds[i + 1].bottom(4)) # mix low p300.mix(2, 200, stds[i + 1].bottom(8)) # mix mid p300.mix(5, 200, stds[i + 1].bottom(16)) # mix hi # blow out just below the surface p300.blow_out(stds[i + 1].bottom(16)) p300.drop_tip() # Add to PCR samples # Add sample DNA, mix, distribute to strip tubes for i, mixtube in enumerate(stds_to_add_to_PCR_tubes): for y in range(0, len(holderList)): #usually length 1 or 2 p300.pick_up_tip() p300.move_to(mixtube.bottom(40)) p300.aspirate(num_of_sample_reps_per_holder * 20 * 1.10, mixtube.bottom(2)) # 6*20*1.08 = 130 protocol.delay(seconds=1) #equilibrate p300.touch_tip(v_offset=-3) holderPos = y holder = holderList[holderPos] for x in range(num_of_sample_reps_per_holder): # samples in holder row = SAMP_wells[i] dest = row + str(2 * x + 1) # need +1 offset for col p300.move_to( holder[dest].bottom(40)) #move across holder in +4cm pos p300.dispense( 20, holder[dest].bottom(6), rate=0.75) # more height so tip doesn't touch pellet p300.touch_tip() p300.move_to(holder[dest].top( )) # centers tip so tip doesn't lift tubes after touch p300.move_to( holder[dest].bottom(40)) #move across holder in +4cm pos p300.drop_tip()
def run(protocol: protocol_api.ProtocolContext): ################################ Variable input below ###################################################### # Sample information target_con = 10 # This is the final concentration we are diluting to current_tip_20 = "B1" # Where the P20 single should start on tip box. current_tip_300 = "B1" # Where the p300 single should start on the tip box water_location = "A1" # Location of master mix on tube_rack2 water_loaded = False # if you have already loaded the water for some reason this turns to True # Need to add a specification on what tip rack column to start on ############################################# Code that allows stuff to work ########################################## # # Creating an array for the sample plate alphabate = [ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P' ] tube_rack_array = np.zeros((4, 6), dtype='U25') for col1 in range(0, 6): for row1 in range(0, 4): tube_rack_array[row1, col1] = alphabate[row1] + str(col1 + 1) # # labware tiprack_20 = protocol.load_labware('opentrons_96_filtertiprack_20ul', tip_rack_20_loc) tip_rack_300 = protocol.load_labware('opentrons_96_tiprack_300ul', tip_rack_300_loc) tube_rack_15ml = protocol.load_labware( 'opentrons_15_tuberack_falcon_15ml_conical', tube_rack_15ml_loc) tube_rack1 = protocol.load_labware( 'opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap', tube_rack1_loc) tube_rack2 = protocol.load_labware( 'opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap', tube_rack2_loc) tube_rack3 = protocol.load_labware( 'opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap', tube_rack3_loc) tube_rack4 = protocol.load_labware( 'opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap', tube_rack4_loc) tube_rack5 = protocol.load_labware( 'opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap', tube_rack5_loc) tube_rack6 = protocol.load_labware( 'opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap', tube_rack6_loc) tube_rack7 = protocol.load_labware( 'opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap', tube_rack7_loc) tube_rack8 = protocol.load_labware( 'opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap', tube_rack8_loc) # # pipettes left_pipette = protocol.load_instrument('p20_single_gen2', 'left', tip_racks=[tiprack_20]) right_pipette = protocol.load_instrument('p300_single_gen2', 'right', tip_racks=[tip_rack_300]) # # Set starting tip left_pipette.starting_tip = tiprack_20.wells_by_name()[current_tip_20] right_pipette.starting_tip = tip_rack_300.wells_by_name()[current_tip_300] # # setting water location water_well = tube_rack_15ml.wells_by_name()[water_location] # # formatting data better aspirations = set_up_data(concentrations, target_con) # commands # Loading water if not water_loaded: right_pipette.pick_up_tip() for i in range(0, len(aspirations)): water_drop = get_tube_positions(i, tube_rack_array) if (i > 71) & (i <= 95): right_pipette.transfer(aspirations[2][i], water_well, tube_rack8.wells_by_name()[water_drop], new_tip='never', air_gap=5) if (i > 47) & (i <= 71): right_pipette.transfer(aspirations[2][i], water_well, tube_rack6.wells_by_name()[water_drop], new_tip='never', air_gap=5) if (i > 23) & (i <= 47): right_pipette.transfer(aspirations[2][i], water_well, tube_rack4.wells_by_name()[water_drop], new_tip='never', air_gap=5) if (i >= 0) & (i <= 23): right_pipette.transfer(aspirations[2][i], water_well, tube_rack2.wells_by_name()[water_drop], new_tip='never', air_gap=5) right_pipette.drop_tip() # adding sample to water for i in range(0, len(aspirations)): tube_position = get_tube_positions(i, tube_rack_array) if (i > 71) & (i <= 95): left_pipette.transfer(aspirations[1][i], tube_rack7.wells_by_name()[tube_position], tube_rack8.wells_by_name()[tube_position], air_gap=3, rate=2.0) if (i > 47) & (i <= 71): left_pipette.transfer(aspirations[1][i], tube_rack5.wells_by_name()[tube_position], tube_rack6.wells_by_name()[tube_position], air_gap=3, rate=2.0) if (i > 23) & (i <= 47): left_pipette.transfer(aspirations[1][i], tube_rack3.wells_by_name()[tube_position], tube_rack4.wells_by_name()[tube_position], air_gap=3, rate=2.0) if (i >= 0) & (i <= 23): left_pipette.transfer(aspirations[1][i], tube_rack1.wells_by_name()[tube_position], tube_rack2.wells_by_name()[tube_position], air_gap=3, rate=2.0)
def run(protocol: protocol_api.ProtocolContext): """ Pick up p20 and/or p300 tips, followed by touch bottom of tubes of different labware """ # ============================================================================= # LOADING LABWARE============================================================== # ============================================================================= labwares = [] ## empty list to add labware to, to loop through ##### Loading pipettetips if pipette300: tips_200 = protocol.load_labware('opentrons_96_filtertiprack_200ul', 10, '200tips') if pipette20: tips_20 = protocol.load_labware('opentrons_96_filtertiprack_20ul', 11, '20tips') ##### Loading labware if plate: plate_96 = protocol.load_labware('biorad_96_wellplate_200ul_pcr', 1, '96well_plate') labwares.append(plate_96) if plate_on_rack: plate_coolrack = protocol.load_labware( 'biorad_qpcr_plate_eppendorf_cool_rack', 2, '96well_plate_on_rack') labwares.append(plate_coolrack) if strips: pcr_strips = protocol.load_labware('pcrstrips_96_wellplate_200ul', 3, 'pcr_strips') labwares.append(pcr_strips) if tubes: sample_tubes = protocol.load_labware( 'opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap', 4, 'sample_tubes') labwares.append(sample_tubes) if tubes5mL: tubes_5mL = protocol.load_labware( 'eppendorfscrewcap_15_tuberack_5000ul', 5, 'tubes_5mL') labwares.append(tubes_5mL) ##### Loading pipettes if pipette300: p300 = protocol.load_instrument('p300_single_gen2', 'right', tip_racks=[tips_200]) if pipette20: p20 = protocol.load_instrument('p20_single_gen2', 'left', tip_racks=[tips_20]) # ============================================================================= # START-UP===================================================================== # ============================================================================= protocol.set_rail_lights(True) ## turn on lights if pipette300: p300.starting_tip = tips_200.well(p300_start_tip) ## define first tip p300.pick_up_tip() ## pick up first tip if pipette20: p20.starting_tip = tips_20.well(p20_start_tip) ## define first tip p20.pick_up_tip() ## pick up first tip # ============================================================================= # test labwares # ============================================================================= for labware in labwares: # wells wells = [] if test_wells: all_wells = labware.wells() total_number_of_wells = len(all_wells) middle = int(total_number_of_wells / 2) wells.append(all_wells[0]) wells.append(all_wells[middle]) wells.append(all_wells[-1]) ## pick 3 wells, nicely distributed of the labware if test_columns: all_columns = labware.columns() total_number_of_columns = len(all_columns) middle = int(total_number_of_columns / 2) columns = [] columns.append(all_columns[0]) columns.append(all_columns[middle]) columns.append(all_columns[-1]) ## pick 3 columns, nicely distributed of the labware for column in columns: for well in column: wells.append(well) for well in wells: if pipette300: p300.move_to(well.bottom()) protocol.delay(seconds=1) for well in wells: if pipette20: p20.move_to(well.bottom()) protocol.delay(seconds=1) # ============================================================================= # SHUT DOWN==================================================================== # ============================================================================= if pipette300: p300.return_tip() if pipette20: p20.return_tip() protocol.set_rail_lights(False) # =============================================================================
def run(ctx: protocol_api.ProtocolContext): ctx.comment('Actual used columns: ' + str(num_cols)) # Define the STEPS of the protocol STEP = 0 STEPS = { # Dictionary with STEP activation, description, and times 1: {'Execute': True, 'description': 'Add 300 ul Wash Buffer 1 - Round 1'}, 2: {'Execute': True, 'description': 'Add 300 ul Wash Buffer 1 - Round 2'}, 3: {'Execute': True, 'description': 'Add 450 ul Wash Buffer 2 - Round 1'}, 4: {'Execute': True, 'description': 'Add 450 ul Wash Buffer 2 - Round 2'}, 5: {'Execute': True, 'description': 'Add 50 ul Elution Buffer'}, } for s in STEPS: # Create an empty wait_time if 'wait_time' not in STEPS[s]: STEPS[s]['wait_time'] = 0 folder_path = '/var/lib/jupyter/notebooks/'+run_id if not ctx.is_simulating(): if not os.path.isdir(folder_path): os.mkdir(folder_path) file_path = folder_path + '/KB_PlateFilling_pathogen_time_log.txt' # Define Reagents as objects with their properties class Reagent: def __init__(self, name, flow_rate_aspirate, flow_rate_dispense, rinse, reagent_reservoir_volume, delay, num_wells, h_cono, v_fondo, tip_recycling = 'none'): self.name = name self.flow_rate_aspirate = flow_rate_aspirate self.flow_rate_dispense = flow_rate_dispense self.rinse = bool(rinse) self.reagent_reservoir_volume = reagent_reservoir_volume self.delay = delay #Delay of reagent in dispense self.num_wells = num_wells self.col = 0 self.vol_well = 0 self.h_cono = h_cono self.v_cono = v_fondo self.unused=[] self.tip_recycling = tip_recycling self.vol_well_original = reagent_reservoir_volume / num_wells # Reagents and their characteristics WashBuffer1 = Reagent(name='Wash Buffer 1', flow_rate_aspirate=0.75, flow_rate_dispense=1, rinse=True, delay=2, reagent_reservoir_volume=100000, num_wells=1, h_cono=0, v_fondo=0) # Flat surface WashBuffer2 = Reagent(name='Wash Buffer 1', flow_rate_aspirate=0.75, flow_rate_dispense=1, rinse=True, delay=2, reagent_reservoir_volume=100000, num_wells=1, h_cono=0, v_fondo=0) # Flat surface ElutionBuffer = Reagent(name='Elution Buffer', flow_rate_aspirate=1, flow_rate_dispense=1, rinse=False, delay=0, reagent_reservoir_volume=50*NUM_SAMPLES, num_wells=1, h_cono=1.95, v_fondo=695) # Prismatic WashBuffer1.vol_well = WashBuffer1.vol_well_original WashBuffer2.vol_well = WashBuffer2.vol_well_original ElutionBuffer.vol_well = ElutionBuffer.vol_well_original ################## # Custom functions 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(radius=0.9, speed = 20, v_offset = -5) #radius here is 0.9 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 calc_height(reagent, cross_section_area, aspirate_volume, min_height = 0.5): nonlocal ctx ctx.comment('Remaining volume ' + str(reagent.vol_well) + '< needed volume ' + str(aspirate_volume) + '?') if reagent.vol_well < aspirate_volume: reagent.unused.append(reagent.vol_well) ctx.comment('Next column should be picked') ctx.comment('Previous to change: ' + str(reagent.col)) # column selector position; intialize to required number reagent.col = reagent.col + 1 ctx.comment(str('After change: ' + str(reagent.col))) reagent.vol_well = reagent.vol_well_original ctx.comment('New volume:' + str(reagent.vol_well)) height = (reagent.vol_well - aspirate_volume - reagent.v_cono) / cross_section_area #- reagent.h_cono reagent.vol_well = reagent.vol_well - aspirate_volume ctx.comment('Remaining volume:' + str(reagent.vol_well)) if height < min_height: height = min_height col_change = True else: height = (reagent.vol_well - aspirate_volume - reagent.v_cono) / cross_section_area #- reagent.h_cono reagent.vol_well = reagent.vol_well - aspirate_volume ctx.comment('Calculated height is ' + str(height)) if height < min_height: height = min_height ctx.comment('Used height is ' + str(height)) col_change = False return height, col_change ########## # pick up tip and if there is none left, prompt user for a new rack def pick_up(pip): nonlocal tip_track if not ctx.is_simulating(): if tip_track['counts'][pip] == tip_track['maxes'][pip]: ctx.pause('Replace ' + str(pip.max_volume) + 'µl tipracks before \ resuming.') pip.reset_tipracks() tip_track['counts'][pip] = 0 pip.pick_up_tip() ########## def find_side(col): ''' Detects if the current column has the magnet at its left or right side ''' if col % 2 == 0: side = -1 # left else: side = 1 return side #################################### # load labware and modules # 12 well rack #################################### reagent_res = ctx.load_labware( 'nest_12_reservoir_15ml', '3', 'Reservoir 12 channel, column 1') # WashBuffer1 reservoir #################################### WashBuffer1_reservoir = ctx.load_labware( 'nalgene_1_reservoir_300000ul', '2', 'Ethanol 80% reservoir') # WashBuffer2 reservoir #################################### WashBuffer2_reservoir = ctx.load_labware( 'nalgene_1_reservoir_300000ul', '11', 'WashBuffer reservoir') # Wash Buffer 1 300ul Deepwell plate ############################################ WashBuffer1_300ul_plate1 = ctx.load_labware( 'kf_96_wellplate_2400ul', '1', 'Wash Buffer 1 Deepwell plate 1') # Wash Buffer 1 300ul Deepwell plate ############################################ WashBuffer1_300ul_plate2 = ctx.load_labware( 'kf_96_wellplate_2400ul', '4', 'Wash Buffer 1 Deepwell plate 2') # Wash Buffer 2 450ul Deepwell plate ############################################ WashBuffer2_450ul_plate1 = ctx.load_labware( 'kf_96_wellplate_2400ul', '7', 'Wash Buffer 2 Deepwell plate 1') # Wash Buffer 2 450ul Deepwell plate ############################################ WashBuffer2_450ul_plate2 = ctx.load_labware( 'kf_96_wellplate_2400ul', '10', 'Wash Buffer 2 Deepwell plate 2') # Elution Deepwell plate ############################################ ElutionBuffer_50ul_plate = ctx.load_labware( 'kingfisher_std_96_wellplate_550ul', '6', 'Elution Buffer 50 ul STD plate') #################################### # Load tip_racks tips300 = [ctx.load_labware('opentrons_96_tiprack_300ul', slot, '200µl filter tiprack') for slot in ['8']] ################################################################################ # Declare which reagents are in each reservoir as well as deepwell and elution plate WashBuffer1.reagent_reservoir = WashBuffer1_reservoir.wells()[0] WashBuffer2.reagent_reservoir = WashBuffer2_reservoir.wells()[0] ElutionBuffer.reagent_reservoir = reagent_res.rows()[0][0] # columns in destination plates to be filled depending the number of samples wb1plate1_destination = WashBuffer1_300ul_plate1.rows()[0][:num_cols] wb1plate2_destination = WashBuffer1_300ul_plate2.rows()[0][:num_cols] wb2plate1_destination = WashBuffer2_450ul_plate1.rows()[0][:num_cols] wb2plate2_destination = WashBuffer2_450ul_plate2.rows()[0][:num_cols] elutionbuffer_destination = ElutionBuffer_50ul_plate.rows()[0][:num_cols] # pipette m300 = ctx.load_instrument( 'p300_multi_gen2', 'right', tip_racks=tips300) # Load multi pipette # used tip counter and set maximum tips available tip_track = { 'counts': {m300: 0}, 'maxes': {m300: len(tips300)*96} } ############################################################################ # STEP 1 Filling with WashBuffer1 plate 1 ############################################################################ STEP += 1 if STEPS[STEP]['Execute'] == True: start = datetime.now() ctx.comment('Step ' + str(STEP) + ': ' + STEPS[STEP]['description']) ctx.comment('###############################################') wash_buffer_vol = [150, 150] rinse = False # Only first time ######## # Wash buffer dispense for i in range(num_cols): if not m300.hw_pipette['has_tip']: pick_up(m300) for j, transfer_vol in enumerate(wash_buffer_vol): if (i == 0 and j == 0): rinse = True #Rinse only first transfer else: rinse = False move_vol_multichannel(m300, reagent = WashBuffer1, source = WashBuffer1.reagent_reservoir, dest = wb1plate1_destination[i], vol = transfer_vol, air_gap_vol = air_gap_vol, x_offset = x_offset, pickup_height = 1, rinse = rinse, disp_height = -2, blow_out = True, touch_tip = True) m300.drop_tip(home_after=True) tip_track['counts'][m300] += 8 end = datetime.now() time_taken = (end - start) ctx.comment('Step ' + str(STEP) + ': ' + STEPS[STEP]['description'] + ' took ' + str(time_taken)) STEPS[STEP]['Time:'] = str(time_taken) ############################################################################ # STEP 2 Filling with WashBuffer1 plate 2 ############################################################################ STEP += 1 if STEPS[STEP]['Execute'] == True: start = datetime.now() ctx.comment('Step ' + str(STEP) + ': ' + STEPS[STEP]['description']) ctx.comment('###############################################') wash_buffer_vol = [150, 150] rinse = False # Only first time ######## # Wash buffer dispense for i in range(num_cols): if not m300.hw_pipette['has_tip']: pick_up(m300) for j, transfer_vol in enumerate(wash_buffer_vol): if (i == 0 and j == 0): rinse = True else: rinse = False move_vol_multichannel(m300, reagent = WashBuffer1, source = WashBuffer1.reagent_reservoir, dest = wb1plate2_destination[i], vol = transfer_vol, air_gap_vol = air_gap_vol, x_offset = x_offset, pickup_height = 1, rinse = rinse, disp_height = -2, blow_out = True, touch_tip = True) m300.drop_tip(home_after=True) tip_track['counts'][m300] += 8 end = datetime.now() time_taken = (end - start) ctx.comment('Step ' + str(STEP) + ': ' + STEPS[STEP]['description'] + ' took ' + str(time_taken)) STEPS[STEP]['Time:'] = str(time_taken) ############################################################################ # STEP 3 Filling with WashBuffer2 plate 1 ############################################################################ STEP += 1 if STEPS[STEP]['Execute'] == True: start = datetime.now() ctx.comment('Step ' + str(STEP) + ': ' + STEPS[STEP]['description']) ctx.comment('###############################################') wash_buffer_vol = [150, 150, 150] rinse = False # Only first time ######## # Wash buffer dispense for i in range(num_cols): if not m300.hw_pipette['has_tip']: pick_up(m300) for j, transfer_vol in enumerate(wash_buffer_vol): if (i == 0 and j == 0): rinse = True else: rinse = False move_vol_multichannel(m300, reagent = WashBuffer2, source = WashBuffer2.reagent_reservoir, dest = wb2plate1_destination[i], vol = transfer_vol, air_gap_vol = air_gap_vol, x_offset = x_offset, pickup_height = 1, rinse = rinse, disp_height = -2, blow_out = True, touch_tip = True) m300.drop_tip(home_after=True) tip_track['counts'][m300] += 8 end = datetime.now() time_taken = (end - start) ctx.comment('Step ' + str(STEP) + ': ' + STEPS[STEP]['description'] + ' took ' + str(time_taken)) STEPS[STEP]['Time:'] = str(time_taken) ############################################################################ # STEP 4 Filling with WashBuffer2 plate 2 ############################################################################ STEP += 1 if STEPS[STEP]['Execute'] == True: start = datetime.now() ctx.comment('Step ' + str(STEP) + ': ' + STEPS[STEP]['description']) ctx.comment('###############################################') ethanol_vol = [150, 150, 150] rinse = False # Only first time ######## # Ethanol dispense for i in range(num_cols): if not m300.hw_pipette['has_tip']: pick_up(m300) for j, transfer_vol in enumerate(ethanol_vol): if (i == 0 and j == 0): rinse = True else: rinse = False move_vol_multichannel(m300, reagent = WashBuffer2, source = WashBuffer2.reagent_reservoir, dest = wb2plate2_destination[i], vol = transfer_vol, air_gap_vol = air_gap_vol, x_offset = x_offset, pickup_height = 1, rinse = rinse, disp_height = -2, blow_out = True, touch_tip = True) m300.drop_tip(home_after=True) tip_track['counts'][m300] += 8 end = datetime.now() time_taken = (end - start) ctx.comment('Step ' + str(STEP) + ': ' + STEPS[STEP]['description'] + ' took ' + str(time_taken)) STEPS[STEP]['Time:'] = str(time_taken) ############################################################################ # STEP 5 Transfer Elution buffer ############################################################################ STEP += 1 if STEPS[STEP]['Execute'] == True: start = datetime.now() ctx.comment('Step ' + str(STEP) + ': ' + STEPS[STEP]['description']) ctx.comment('###############################################') # Elution buffer ElutionBuffer_vol = [50] ######## # Water or elution buffer for i in range(num_cols): if not m300.hw_pipette['has_tip']: pick_up(m300) for transfer_vol in ElutionBuffer_vol: # Calculate pickup_height based on remaining volume and shape of container [pickup_height, change_col] = calc_height( ElutionBuffer, multi_well_rack_area, transfer_vol * 8) ctx.comment( 'Aspirate from Reservoir column: ' + str(ElutionBuffer.col)) ctx.comment('Pickup height is ' + str(pickup_height)) move_vol_multichannel(m300, reagent = ElutionBuffer, source = ElutionBuffer.reagent_reservoir, dest = elutionbuffer_destination[i], vol = transfer_vol, air_gap_vol = air_gap_vol_elutionbuffer, x_offset = x_offset, pickup_height = pickup_height, rinse = False, disp_height = -2, blow_out = True, touch_tip = False) m300.drop_tip(home_after=True) tip_track['counts'][m300] += 8 end = datetime.now() time_taken = (end - start) ctx.comment('Step ' + str(STEP) + ': ' + STEPS[STEP]['description'] + ' took ' + str(time_taken)) STEPS[STEP]['Time:'] = str(time_taken) # Export the time log to a tsv file if not ctx.is_simulating(): with open(file_path, 'w') as f: f.write('STEP\texecution\tdescription\twait_time\texecution_time\n') for key in STEPS.keys(): row = str(key) for key2 in STEPS[key].keys(): row += '\t' + format(STEPS[key][key2]) f.write(row + '\n') f.close() ############################################################################ # Light flash end of program from opentrons.drivers.rpi_drivers import gpio for i in range(3): gpio.set_rail_lights(False) gpio.set_button_light(1, 0, 0) time.sleep(0.3) gpio.set_rail_lights(True) gpio.set_button_light(0, 0, 1) time.sleep(0.3) gpio.set_button_light(0, 1, 0) ctx.comment( 'Finished! \nMove deepwell plates to KingFisher extractor.') ctx.comment('Used tips in total: ' + str(tip_track['counts'][m300])) ctx.comment('Used racks in total: ' + str(tip_track['counts'][m300] / 96))
def run(ctx: protocol_api.ProtocolContext): STEP = 0 STEPS = { # Dictionary with STEP activation, description and times 1: { 'Execute': False, 'description': 'Dispensar Proteinasa K (' + str(PK_VOL_PER_SAMPLE) + 'ul)' }, 2: { 'Execute': True, 'description': 'Mezclar y dispensar muestras (' + str(VOLUME_SAMPLE) + 'ul)' } } for s in STEPS: # Create an empty wait_time if 'wait_time' not in STEPS[s]: STEPS[s]['wait_time'] = 0 #Folder and file_path for log time if not ctx.is_simulating(): folder_path = '/var/lib/jupyter/notebooks/' + run_id if not os.path.isdir(folder_path): os.mkdir(folder_path) file_path = folder_path + '/StationA_time_log.txt' # Define Reagents as objects with their properties class Reagent: def __init__(self, name, flow_rate_aspirate, flow_rate_dispense, rinse, reagent_reservoir_volume, delay, num_wells): self.name = name self.flow_rate_aspirate = flow_rate_aspirate self.flow_rate_dispense = flow_rate_dispense self.rinse = bool(rinse) self.reagent_reservoir_volume = reagent_reservoir_volume self.delay = delay self.num_wells = num_wells self.vol_well = 0 self.unused = [] self.vol_well_original = reagent_reservoir_volume / num_wells # Reagents and their characteristics Samples = Reagent( name='Samples', flow_rate_aspirate=25, flow_rate_dispense=100, rinse=False, delay=0, reagent_reservoir_volume=0, num_wells=96, ) Pk = Reagent(name='Pk', rinse=False, flow_rate_aspirate=3, flow_rate_dispense=3, reagent_reservoir_volume=1800, num_wells=1, delay=0) ctx.comment(' ') ctx.comment('###############################################') ctx.comment('CONTROLES: ' + str(NUM_CONTROL_SPACES)) ctx.comment('MUESTRAS: ' + str(NUM_REAL_SAMPLES)) ctx.comment('###############################################') ctx.comment(' ') ################## # Custom functions def divide_destinations(l, n): # Divide the list of destinations in size n lists. for i in range(0, len(l), n): yield l[i:i + n] def distribute_custom(pipette, volume, src, dest, waste_pool, pickup_height, extra_dispensal, dest_x_offset, disp_height=0, touch_tip=False, num_shakes=0): pipette.aspirate((len(dest) * volume) + extra_dispensal, src.bottom(pickup_height)) if touch_tip: pipette.touch_tip(speed=20, v_offset=-5) for d in dest: drop = d.top(z=disp_height) pipette.dispense(volume, drop) shake_pipet(pipette, rounds=num_shakes, v_offset=disp_height) 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 move_vol_multichannel(pipet, reagent, source, dest, vol, air_gap_vol, x_offset, pickup_height, rinse, disp_height, blow_out, touch_tip, shakes=0, shake_v_offset=-45): ''' 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 shakes > 0: shake_pipet(pipet, v_offset=shake_v_offset) 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=disp_height)) if touch_tip == True: pipet.touch_tip(speed=20, v_offset=-10) if air_gap_vol != 0: pipet.air_gap(air_gap_vol, height=disp_height) #air gap def custom_mix(pipet, reagent, location, vol, rounds, blow_out, mix_height, x_offset, source_height=5): ''' 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 generate_source_table(source): ''' Concatenate the wells frome the different origin racks ''' num_cols = math.ceil(num_samples / 8) s = [] for i in range(num_cols): if i < 6: s += source[0].columns()[i] + source[1].columns()[i] else: s += source[2].columns()[i - 6] + source[3].columns()[i - 6] return s def shake_pipet(pipet, rounds=2, speed=100, v_offset=0): ctx.comment("Shaking " + str(rounds) + " rounds.") for i in range(rounds): pipet.touch_tip(speed=speed, radius=0.1, v_offset=v_offset) ########## # pick up tip and if there is none left, prompt user for a new rack def pick_up(pip): nonlocal tip_track if not ctx.is_simulating(): if tip_track['counts'][pip] == tip_track['maxes'][pip]: ctx.pause('Replace ' + str(pip.max_volume) + 'µl tipracks before \ resuming.') pip.reset_tipracks() tip_track['counts'][pip] = 0 pip.pick_up_tip() def run_quiet_process(command): subprocess.check_output('{} &> /dev/null'.format(command), shell=True) def play_sound(filename): print('Speaker') print('Next\t--> CTRL-C') try: run_quiet_process('mpg123 {}'.format(path_sounds + filename + '.mp3')) run_quiet_process('mpg123 {}'.format(path_sounds + sonido_defecto)) run_quiet_process('mpg123 {}'.format(path_sounds + filename + '.mp3')) except KeyboardInterrupt: pass print() def start_run(): ctx.comment(' ') ctx.comment('###############################################') ctx.comment('Empezando protocolo') if PHOTOSENSITIVE == False: ctx._hw_manager.hardware.set_lights(button=True, rails=True) else: ctx._hw_manager.hardware.set_lights(button=True, rails=False) now = datetime.now() # dd/mm/YY H:M:S start_time = now.strftime("%Y/%m/%d %H:%M:%S") return start_time def finish_run(switch_off_lights=False): ctx.comment('###############################################') ctx.comment('Protocolo finalizado') ctx.comment(' ') #Set light color to blue ctx._hw_manager.hardware.set_lights(button=True, rails=False) now = datetime.now() # dd/mm/YY H:M:S finish_time = now.strftime("%Y/%m/%d %H:%M:%S") if PHOTOSENSITIVE == False: for i in range(10): ctx._hw_manager.hardware.set_lights(button=False, rails=False) time.sleep(0.3) ctx._hw_manager.hardware.set_lights(button=True, rails=True) time.sleep(0.3) else: for i in range(10): ctx._hw_manager.hardware.set_lights(button=False, rails=False) time.sleep(0.3) ctx._hw_manager.hardware.set_lights(button=True, rails=False) time.sleep(0.3) if switch_off_lights: ctx._hw_manager.hardware.set_lights(button=True, rails=False) used_tips = tip_track['num_refills'][p1000] * 96 * len( p1000.tip_racks) + tip_track['counts'][p1000] ctx.comment('Puntas de 1000 ul utilizadas: ' + str(used_tips) + ' (' + str(round(used_tips / 96, 2)) + ' caja(s))') ctx.comment('###############################################') if not ctx.is_simulating(): for i in range(SOUND_NUM_PLAYS): if i > 0: time.sleep(60) play_sound('finished_process_esp') return finish_time #################################### # load labware and modules #################################### # Load Sample racks if num_samples <= 48: rack_num = 2 ctx.comment('Used source racks are ' + str(rack_num)) else: rack_num = 4 #source_racks = [ctx.load_labware( # 'pcr_24_wellplate_13200ul', slot, # 'source tuberack with snapcap' + str(i + 1)) for i, slot in enumerate(['4', '1', '5', '2'][:rack_num]) #] source_racks = [ ctx.load_labware('vitrobiocomma_24_tuberack_15000ul_1', '4', 'samples grid 1'), ctx.load_labware('vitrobiocomma_24_tuberack_15000ul_2', '1', 'samples grid 2'), ctx.load_labware('vitrobiocomma_24_tuberack_15000ul_3', '5', 'samples grid 3'), ctx.load_labware('vitrobiocomma_24_tuberack_15000ul_4', '2', 'samples grid 4') ] ################################## # Destination plate dest_plate = ctx.load_labware('nest_96_wellplate_2ml_deep', '6', 'NEST 96 Deepwell Plate 2mL') pk_rack = ctx.load_labware('opentrons_24_tuberack_nest_1.5ml_screwcap', '3', 'opentrons_24_tuberack_nest_1.5ml_screwcap') #################################### # Load tip_racks tips1000 = [ ctx.load_labware( 'opentrons_96_filtertiprack_1000ul' if OPENTRONS_TIPS else 'geb_96_tiprack_1000ul', slot, '1000µl filter tiprack') for slot in ['8'] ] tips300 = [ ctx.load_labware('opentrons_96_tiprack_300ul', slot) for slot in ['7'] ] ################################################################################ # Declare which reagents are in each reservoir as well as deepwell and elution plate Pk.reagent_reservoir = pk_rack.rows()[0][0] # A1 ################################################################################ # setup samples and destinations sample_sources_full = generate_source_table(source_racks) sample_sources = sample_sources_full[NUM_CONTROL_SPACES:num_samples] destinations = dest_plate.wells()[NUM_CONTROL_SPACES:num_samples] # Divide destination wells in small groups for P300 pipette dests = list(divide_destinations(destinations, size_transfer)) p1000 = ctx.load_instrument('p1000_single_gen2', 'left', tip_racks=tips1000) # load P1000 pipette p300 = ctx.load_instrument('p300_single_gen2', mount='right', tip_racks=tips300) # used tip counter and set maximum tips available tip_track = { 'counts': { p1000: 0, p300: 0 }, 'maxes': { p1000: 96 * len(p1000.tip_racks), p300: 96 * len(p300.tip_racks) }, #96 tips per tiprack * number or tipracks in the layout 'num_refills': { p1000: 0, p300: 0 }, 'tips': { p1000: [tip for rack in tips1000 for tip in rack.rows()[0]], p300: [tip for rack in tips300 for tip in rack.rows()[0]] } } start_run() ############################################################################ # STEP 1: DISPENSAR PK ############################################################################ STEP += 1 if STEPS[STEP]['Execute'] == True: start = datetime.now() ctx.comment(' ') ctx.comment('###############################################') ctx.comment('Step ' + str(STEP) + ': ' + STEPS[STEP]['description']) ctx.comment('###############################################') ctx.comment(' ') pick_up(p300) used_vol = [] for dest in dests: ctx.comment( 'dest length ---------------------------------------------- ' + str(len(dest))) aspirate_volume = PK_VOL_PER_SAMPLE * len(dest) + extra_dispensal used_vol_temp = distribute_custom(p300, volume=PK_VOL_PER_SAMPLE, src=Pk.reagent_reservoir, dest=dest, touch_tip=False, waste_pool=Pk.reagent_reservoir, pickup_height=0.2, extra_dispensal=extra_dispensal, dest_x_offset=0, disp_height=-15, num_shakes=PK_SAKES) used_vol.append(used_vol_temp) p300.drop_tip(home_after=False) tip_track['counts'][p300] += 1 end = datetime.now() time_taken = (end - start) ctx.comment('Step ' + str(STEP) + ': ' + STEPS[STEP]['description'] + ' took ' + str(time_taken)) STEPS[STEP]['Time:'] = str(time_taken) ############################################################################ # STEP 2: MIX AND MOVE SAMPLES ############################################################################ STEP += 1 if STEPS[STEP]['Execute'] == True: ctx.comment('Step ' + str(STEP) + ': ' + STEPS[STEP]['description']) ctx.comment('###############################################') start = datetime.now() for s, d in zip(sample_sources, destinations): if not p1000.hw_pipette['has_tip']: pick_up(p1000) # Mix the sample BEFORE dispensing if NUM_MIXES > 0: custom_mix(p1000, reagent=Samples, location=s, vol=volume_mix, rounds=NUM_MIXES, blow_out=True, mix_height=5, x_offset=x_offset) move_vol_multichannel(p1000, reagent=Samples, source=s, dest=d, vol=VOLUME_SAMPLE, air_gap_vol=air_gap_vol_sample, x_offset=x_offset, pickup_height=5, rinse=Samples.rinse, disp_height=-10, blow_out=True, touch_tip=False, shakes=SAMPLE_SAKES) p1000.drop_tip(home_after=False) tip_track['counts'][p1000] += 1 # Time statistics end = datetime.now() time_taken = (end - start) ctx.comment('Step ' + str(STEP) + ': ' + STEPS[STEP]['description'] + ' took ' + str(time_taken)) STEPS[STEP]['Time:'] = str(time_taken) # Export the time log to a tsv file if not ctx.is_simulating(): with open(file_path, 'w') as f: f.write( 'STEP\texecution\tdescription\twait_time\texecution_time\n') for key in STEPS.keys(): row = str(key) for key2 in STEPS[key].keys(): row += '\t' + format(STEPS[key][key2]) f.write(row + '\n') f.close() ############################################################################ # Light flash end of program # from opentrons.drivers.rpi_drivers import gpio finish_run(switch_off_lights)
def run(protocol: protocol_api.ProtocolContext): """Function to transfer 100ul from 1 well to another.""" #loading labware (from opentrons labware library) plate = protocol.load_labware('biorad_96_wellplate_200ul_pcr', 1, '96plate') tiprack_1 = protocol.load_labware('opentrons_96_tiprack_300ul', 2, '300tips') #load pipette p300 = protocol.load_instrument('p300_single_gen2', 'right', tip_racks=[tiprack_1]) #run protocol while protocol.door_closed: if not protocol.door_closed: protocol.set_rail_lights(True) protocol.home() protocol.pause('Press resume when you are ready :)!') protocol.set_rail_lights(False) #transfer 100ul from plate well A1 to plate well B1 with default settings p300.pick_up_tip() #aspirate & dispense at default flow rate of 92.86 ul/s p300.aspirate(100, plate['A1']) p300.dispense(100, plate['B1']) p300.blow_out() #blow out in current location p300.drop_tip() #automatically in trash #all following pipetting steps with changed default flow rates #aspirate at 150 ul/s p300.flow_rate.aspirate = 150 #dispense at 300 ul/s p300.flow_rate.dispense = 300 #blow out at 200 ul/s p300.flow_rate.blow_out = 200 p300.pick_up_tip() p300.aspirate(100, plate['C1']) p300.dispense(100, plate['D1']) p300.blow_out(plate['D1']) #blow out in destination well p300.drop_tip() #automatically in trash #all following pipetting steps aspirate & dispense other height (in mm) #aspirate 2 mm from bottom p300.well_bottom_clearance.aspirate = 3 #dispense 10 mm from bottom p300.well_bottom_clearance.dispense = 10 p300.pick_up_tip() p300.aspirate(100, plate['E1']) p300.dispense(100, plate['F1']) p300.blow_out(plate['F1']) #blow out in destination well p300.drop_tip() #automatically in trash #display a comment in the opentrons app protocol.comment('Hello you!') #all following pipetting steps with per-axis speed limits #limit x-axis to 50 mm/s protocol.max_speeds['X'] = 50 #limit y-axis to 50 mm/s protocol.max_speeds['Y'] = 50 #limit a-axis to 50 mm/s protocol.max_speeds['A'] = 50 p300.pick_up_tip() p300.aspirate(100, plate['G1']) p300.dispense(100, plate['H1']) p300.blow_out(plate['H1']) #blow out in destination well p300.drop_tip() #automatically in trash #all following pipetting steps with per-axis speed limits to default #reset x-axis speed limit - delete method del protocol.max_speeds['X'] #reset y-axis speed limit - none method protocol.max_speeds['Y'] = None #reset a-axis speed limit - none method protocol.max_speeds['A'] = None p300.pick_up_tip() p300.aspirate(100, plate['B1']) p300.dispense(100, plate['A1']) p300.blow_out(plate['A1']) #blow out in destination well p300.drop_tip() #automatically in trash break
def run(protocol: protocol_api.ProtocolContext): # LABWARE fuge_rack = protocol.load_labware('vwr_24_tuberack_1500ul', '1') stds_rack = protocol.load_labware('vwr_24_tuberack_1500ul', '2') tiprack300 = protocol.load_labware('opentrons_96_filtertiprack_200ul', '8') tiprack20 = protocol.load_labware('opentrons_96_filtertiprack_20ul', '9') tempdeck = protocol.load_module('tempdeck', '10') # plate = tempdeck.load_labware('amplifyt_96_aluminumblock_300ul') plate = tempdeck.load_labware('abi_96_wellplate_250ul') # PIPETTES p300 = protocol.load_instrument('p300_single_gen2', 'left', tip_racks=[tiprack300]) p20 = protocol.load_instrument('p20_single_gen2', 'right', tip_racks=[tiprack20]) # REAGENTS # sds_rack #fuge_rack MIX_master = fuge_rack['D1'] # see sheet, but ~2075 WATER = fuge_rack['A1'] # 1500ul WATER samp_1 = fuge_rack['B1'] # e.g. 0.625uM # empty samp_2 = fuge_rack['B2'] # e.g. 1.25uM # empty samp_3 = fuge_rack['B3'] # e.g. 2.5uM # empty samp_4 = fuge_rack['B4'] # e.g. 5.0uM # empty samp_5 = fuge_rack['B5'] # e.g. 7.5uM # empty samp_6 = fuge_rack['B6'] # e.g. 10uM # empty # user inputs p300_max_vol = 200 mix_master_tot = 96 * 18 * 1.2 # total vol of mastermix mmix_XFR_std_mix = 3 * 18 * 1.14 # transfer this amount to the std mix intermediate tubes that will receive DNA std_dna_XFR_to_std_int = 3 * 2 * 1.14 #transfer this amount DNA to std_int_tubes to mix and aliquot to 3 wells mmix_XFR_samp_wells = 18 * 12 * 1.1 # how much mastermix transferred as bolus to well A1, B1..F1 to receive DNA # lists # all_std_tubes = [std_1, std_2, std_3, std_4, std_5, std_6, std_7, std_8, std_9, std_10, std_11, std_12, std_13, std_14, std_15, std_16] # all_std_tubes = [std_1, std_2, std_3, std_4, std_5, std_6, std_7, std_8] # std_tubes = [std_2, std_3, std_4, std_5, std_6, std_7, std_8, WATER] # std_tubes = [std_1, std_2, std_3, std_4, std_5, std_6, std_7, WATER] # std_mixes = [std_1mix, std_2mix, std_3mix, std_4mix, std_5mix, std_6mix, std_7mix, NTC_mix] # std_wells = ['G1', 'G4', 'G7', 'G10', 'H1', 'H4', 'H7', 'H10'] samp_wells = ['A1', 'B1', 'C1', 'D1', 'E1', 'F1'] # samp_sources = [std_1, std_2, std_3, std_4, std_5, std_6] # samp_sources = [std_12, std_13, std_14, std_15, std_16, std_17] samp_sources = [samp_1, samp_2, samp_3, samp_4, samp_5, samp_6] # ### COMMANDS ###### # # make pos control standards # # transfer from pos_control to make std_1 # pos_control_height = tip_heights(400,1,10) # p20.transfer( # 10, # pos_control.bottom(pos_control_height[0]), #1uM # std_1.bottom(20), # mix_after=(2, 20), # remove residual fluid from tip # touch_tip=True # ) # # serial dilutions in microfuge tubes, 10% diliutions # p300.pick_up_tip() # for i in range(len(all_std_tubes)-1): #don't want out of range because i + 1 # last_std_tube = len(all_std_tubes)-1 # (int) position of last std tube; last tube = WATER # h_mix = 20 # if i==0 or i==last_std_tube: # first or last std tube; not WATER # p300.mix(3, 200, all_std_tubes[i].bottom(h_mix)) # need to add mixes to first and last tubes # p300.mix(5, 200, all_std_tubes[i].bottom(h_mix)) # p300.flow_rate.aspirate = 40 #slow aspirate; no air # p300.aspirate(100,all_std_tubes[i].bottom(h_mix)) # p300.touch_tip() # p300.flow_rate.dispense = 40 #slow dispense # p300.dispense(100, all_std_tubes[i+1]) # p300.flow_rate.aspirate = 92.86 #default # p300.flow_rate.dispense = 92.86 #default # p300.mix(3, 200,all_std_tubes[i+1].bottom(h_mix)) #remove residual inside tip # # p300.move_to(std_wells[i+1].bottom(15)) #come up for blowout # p300.blow_out() # protocol.delay(seconds=2) #wait for bubbles to subside # p300.drop_tip() # # Mastermix contains primers and probe. Everything except DNA. Aliquot to 6 tubes. # # transfer sN_mix to intermediate tubes (std_mixes) # p300.pick_up_tip() # p300.flow_rate.aspirate = 92.86 #default # p300.flow_rate.dispense = 92.86 #default # mmix_h = tip_heightsEpp(mix_master_tot, len(std_mixes), mmix_XFR_std_mix) # # print ("mix_master_tot", mix_master_tot) # # print (len(std_mixes)) # # print (mmix_XFR_std_mix) # # print ("mmix_h", mmix_h) # p300.mix(6, 200, MIX_master.bottom(mmix_h[0])) # top tip height # p300.flow_rate.aspirate = 30 # p300.flow_rate.dispense = 40 # # p300.well_bottom_clearance.aspirate = std_mix_heights[0] #mm # for i, tube in enumerate(std_mixes): # # p300.well_bottom_clearance.aspirate = h #mm # p300.aspirate(mmix_XFR_std_mix, MIX_master.bottom(mmix_h[i])) # 18 * 3 * 1.12-0.05= 54 + 6 =60ul # protocol.delay(seconds=2) #tip equilibrate # p300.move_to(MIX_master.bottom(35)) # excess tip fluid condense # protocol.delay(seconds=3) #tip droplets slide # p300.touch_tip(v_offset=-2) # p300.dispense(mmix_XFR_std_mix, tube.bottom(4)) # p300.blow_out(tube.bottom(8)) # p300.drop_tip() # p300.flow_rate.aspirate = 92.86 #reset to default # p300.flow_rate.dispense = 92.86 #reset to default # # transfer std DNA into intermediate std_mixes tubes and then to plate # for std, intTube, well in zip(std_tubes, std_mixes, std_wells): # p20.pick_up_tip() # p300.pick_up_tip() # p20.flow_rate.aspirate = 4 # p20.flow_rate.dispense = 4 # p20.aspirate(std_dna_XFR_to_std_int, std) #aspirate from std_1 into std_mix (intermediate tube) e.g. 6.42 ul # protocol.delay(seconds=2) #equilibrate # p20.touch_tip() # p20.dispense(std_dna_XFR_to_std_int, intTube) # # p20.move_to(intTube.bottom(3)) # p20.flow_rate.aspirate = 7.56 # p20.flow_rate.dispense = 7.56 # p20.mix(2, 20, intTube.bottom(3)) #ensure vol in tip in intTube and washed # p20.blow_out() # p300.move_to(intTube.bottom(40)) #prevent tip from crashing into tube cap # p300.mix(7, 50, intTube.bottom(3)) # protocol.delay(seconds=2) # # p300.move_to(intTube.bottom(10)) #prevent air bubbles in mmix during blow out # p300.blow_out(intTube.bottom(10)) # p20.move_to(intTube.bottom(40)) # p20.flow_rate.aspirate = 4 # p20.flow_rate.dispense = 4 # for x in range(0,3): # need int 1, 2, and 3 # p20.aspirate(20, intTube.bottom(2)) # protocol.delay(seconds=2) #equilibrate # # find digits in well, G1 and G10 and puts into list # findNums = [int(i) for i in well.split()[0] if i.isdigit()] # # joins nums from list [1, 0] -> 10 type = string # colNum = ''.join(map(str, findNums)) # # this finds row # row = well.split()[0][0] # dest = row+str(int(colNum)+x) # row + neighbor well i.e. 1, 2 # p20.dispense(20, plate[dest].bottom(2)) # protocol.delay(seconds=2) # p20.move_to(plate[dest].bottom(6)) # p20.blow_out() # # p20.touch_tip() # p300.drop_tip() # p20.drop_tip() # p20.flow_rate.aspirate = 7.56 # p20.flow_rate.dispense = 7.56 # # transfer mastermix bolus to beginning wells to receive sample # samp_h = tip_heightsEpp(mix_master_tot-mmix_XFR_std_mix, len(samp_wells), mmix_XFR_samp_wells) # p300.pick_up_tip() # for i, well in enumerate(samp_wells): # vols = split_asp(mmix_XFR_samp_wells, p300_max_vol) #split 237.60 into 2 asp steps # for j, vol in enumerate(vols): # loop through each vol # p300.flow_rate.aspirate = 40 #default # p300.flow_rate.dispense = 40 #default # p300.aspirate(vol, MIX_master.bottom(samp_h[i])) # protocol.delay(seconds=2) # p300.dispense(vol, plate[well].bottom(4*j+5)) # protocol.delay(seconds=1) # p300.blow_out(plate[well].bottom(14)) # p300.touch_tip() # p300.drop_tip() # add dna to first wells, mix, and aliquot to neighbors # six samples, can be changed in the user inputs samp_dna_XFR_to_wells = 2 * 12 * 1.1 # 26.4 2ul in 12 wells + excess for i, (sample, well) in enumerate(zip(samp_sources, samp_wells)): p300.pick_up_tip() p20.pick_up_tip() p300.flow_rate.aspirate = 92.86 p300.flow_rate.dispense = 92.86 p300.mix(3, 200, sample) # mix the sample p300.flow_rate.aspirate = 30 p300.flow_rate.dispense = 40 p300.aspirate(samp_dna_XFR_to_wells, sample.bottom(2)) # sample vol may vary. Goto bottom. p300.move_to(sample.bottom(25)) # relieve pressure if tip at bottom protocol.delay(seconds=2) p300.touch_tip() p300.dispense(samp_dna_XFR_to_wells, plate[well].bottom(3)) p300.flow_rate.aspirate = 92.86 p300.flow_rate.dispense = 92.86 p300.mix(3, 200, plate[well].bottom(5)) # vol = 26.4 + 237.6 = 264 p300.flow_rate.aspirate = 30 p300.flow_rate.dispense = 40 p300.mix(1, 200, plate[well].bottom(3)) p300.move_to(plate[well].bottom(14)) protocol.delay(seconds=2) p300.blow_out(plate[well].bottom(16)) p300.touch_tip() for x in range(1, 12): # need int 1, 2, and 12 # find digits in well, G1 and G10 and puts into list findNums = [int(d) for d in well.split()[0] if d.isdigit()] # joins nums from list [1, 0] -> 10 type = string colNum = ''.join(map(str, findNums)) # this finds row row = well.split()[0][0] dest = row + str(int(colNum) + x) # row + neighbor well i.e. 1, 2 p20.flow_rate.aspirate = 7.56 p20.flow_rate.dispense = 7.56 p20.aspirate(20, plate[well]) p20.move_to(plate[well].bottom(16)) protocol.delay(seconds=2) #equilibrate p20.touch_tip() p20.dispense(20, plate[dest].bottom(2)) protocol.delay(seconds=1) # p20.move_to(plate[dest].bottom(4)) p20.blow_out(plate[dest].bottom(6)) p20.drop_tip() p300.drop_tip()
def run(ctx: protocol_api.ProtocolContext): # Initial data global robot global tip_log # Set robot as global var robot = ctx # check if tipcount is being reset if RESET_TIPCOUNT: reset_tipcount() # confirm door is close robot.comment(f"Please, close the door") confirm_door_is_closed() start = start_run() # ##################################################### # Common functions # ##################################################### # ----------------------------------------------------- # Execute step # ----------------------------------------------------- def run_step(step): robot.comment(' ') robot.comment('###############################################') robot.comment('Step ' + str(step) + ': ' + STEPS[step]['Description']) robot.comment('===============================================') # Execute step? if STEPS[step]['Execute']: # Get start info elapsed = datetime.now() for i, key in enumerate(tip_log['used']): val = tip_log['used'][key] if i == 0: cl = val else: cr = val # Execute function step STEPS[step]['Function']() # Wait if STEPS[step].get('wait_time'): robot.comment( '===============================================') wait = STEPS[step]['wait_time'] robot.delay(seconds=wait) # Get end info elapsed = datetime.now() - elapsed for i, key in enumerate(tip_log['used']): val = tip_log['used'][key] if i == 0: cl = val - cl else: cr = val - cr # Stats STEPS[step]['Time:'] = str(elapsed) robot.comment('===============================================') robot.comment('Elapsed time: ' + str(elapsed)) for i, key in enumerate(tip_log['used']): if i == 0: robot.comment('Tips "' + str(key) + '" used: ' + str(cl)) else: robot.comment('Tips "' + str(key) + '" used: ' + str(cr)) # Dont execute step else: robot.comment('No ejecutado') # End robot.comment('###############################################') robot.comment(' ') # ##################################################### # 1. Start defining deck # ##################################################### # Labware # Positions are: # 10 11 TRASH # 7 8 9 # 4 5 6 # 1 2 3 # ----------------------------------------------------- # Tips # ----------------------------------------------------- tips20 = [ robot.load_labware('opentrons_96_filtertiprack_20ul', slot) for slot in ['11'] ] # ----------------------------------------------------- # Pipettes # ----------------------------------------------------- p20 = robot.load_instrument('p20_single_gen2', 'right', tip_racks=tips20) ## retrieve tip_log retrieve_tip_info(p20, tips20) # ----------------------------------------------------- # Labware # ----------------------------------------------------- positive_control_rack = ctx.load_labware( 'opentrons_24_tuberack_nest_2ml_screwcap', '7', '24_tuberack_starsted source rack') dest_rack = ctx.load_labware( 'opentrons_96_aluminumblock_biorad_wellplate_200ul', '8', 'source tuberack ') # ----------------------------------------------------- # Reagens # ----------------------------------------------------- positive_control_master_mix = Reagent(name='Positive control Master Mix', flow_rate_aspirate=600, flow_rate_dispense=1000, flow_rate_aspirate_mix=600, flow_rate_dispense_mix=1000) # ----------------------------------------------------- # Tubes # ----------------------------------------------------- starsted_tube = Tube( name='Starsted 1.5 Tube', actual_volume=400, max_volume=1500, min_height=0.7, diameter=8.7, # avl1.diameter base_type=2, height_base=4) # ##################################################### # 2. Steps definition # ##################################################### # ----------------------------------------------------- # Step n: .... # ----------------------------------------------------- def step1(): if not p20.hw_pipette['has_tip']: pick_up(p20, tips20) segene_positive_control_mastermix = positive_control_rack['A6'] dest = dest_rack.wells()[:50] # transfer buffer to tubes distribute_custom(pip=p20, reagent=positive_control_master_mix, tube_type=starsted_tube, volume=15, src=segene_positive_control_mastermix, dest=dest, extra_dispensal=0, disp_height=20, touch_tip_aspirate=False, touch_tip_dispense=True) drop(p20) # ----------------------------------------------------- # Execution plan # ----------------------------------------------------- STEPS = { 1: { 'Execute': True, 'Function': step1, 'Description': 'Transfer Primers 20 first wells/tubes' }, } # ##################################################### # 3. Execute every step!! # ##################################################### for step in STEPS: run_step(step) # track final used tip save_tip_info() # ----------------------------------------------------- # Stats # ----------------------------------------------------- end = finish_run() robot.comment('===============================================') robot.comment('Start time: ' + str(start)) robot.comment('Finish time: ' + str(end)) robot.comment('Elapsed time: ' + str( datetime.strptime(end, "%Y/%m/%d %H:%M:%S") - datetime.strptime(start, "%Y/%m/%d %H:%M:%S"))) for key in tip_log['used']: val = tip_log['used'][key] robot.comment('Tips "' + str(key) + '" used: ' + str(val)) robot.comment('===============================================')
def run(protocol: protocol_api.ProtocolContext): """ Aliquoting mastermix from a 5 mL tube to 5x + 2 wells PCR strips in 2x 96-wells plates; using volume tracking so that the pipette starts aspirating at the starting height of the liquid and goes down as the volume decreases. Adding primers from PCR strips (with 10 uM primer F&R primer mix) to PCR strips (with mastermix). """ # ============================================================================= # ======================LOADING LABWARE AND PIPETTES=========================== # ============================================================================= ## For available labware see "labware/list_of_available_labware". ## # Pipette tips tips_200 = protocol.load_labware( 'opentrons_96_filtertiprack_200ul', #labware definition 3, #deck position '200tips') #custom name tips_20 = protocol.load_labware( 'opentrons_96_filtertiprack_20ul', #labware definition 4, #deck position '20tips') #custom name # Tube racks & plates ##### !!! OPTION 1: ROBOT # mastermix_tube = protocol.load_labware( # 'eppendorfscrewcap_15_tuberack_5000ul', #labware def # 5, #deck position # 'mastermix_tube') #custom name # primer_strips_1 = protocol.load_labware( # 'pcrstrips_96_wellplate_200ul', #labware definition # 6, #deck position # 'primer_strips_1') #custom name # primer_strips_2 = protocol.load_labware( # 'pcrstrips_96_wellplate_200ul', #labware definition # 7, #deck position # 'primer_strips_2') #custom name # mastermix_strips_1 = protocol.load_labware( # 'pcrstrips_96_wellplate_200ul', #labware definition # 8, #deck position # 'mastermix_strips_1') #custom name # mastermix_strips_2 = protocol.load_labware( # 'pcrstrips_96_wellplate_200ul', #labware definition # 9, #deck position # 'mastermix_strips_2') #custom name ##### !!! OPTION 2: SIMULATOR with open("labware/eppendorfscrewcap_15_tuberack_5000ul/" "eppendorfscrewcap_15_tuberack_5000ul.json") as labware_file: labware_def_5mL = json.load(labware_file) mastermix_tube = protocol.load_labware_from_definition( labware_def_5mL, #variable derived from opening json 5, #deck position 'mastermix_tube') #custom name with open("labware/pcrstrips_96_wellplate_200ul/" "pcrstrips_96_wellplate_200ul.json") as labware_file: labware_def_pcrstrips = json.load(labware_file) primer_strips_1 = protocol.load_labware_from_definition( labware_def_pcrstrips, #variable derived from opening json 6, #deck position 'primer_strips_1') #custom name primer_strips_2 = protocol.load_labware_from_definition( labware_def_pcrstrips, #variable derived from opening json 7, #deck position 'primer_strips_2') #custom name mastermix_strips_1 = protocol.load_labware_from_definition( labware_def_pcrstrips, #variable derived from opening json 8, #deck position 'mastermix_strips_1') #custom name mastermix_strips_2 = protocol.load_labware_from_definition( labware_def_pcrstrips, #variable derived from opening json 9, #deck position 'mastermix_strips_2') #custom name # Pipettes p300 = protocol.load_instrument( 'p300_single_gen2', #instrument definition 'right', #mount position tip_racks=[tips_200]) #assigned tiprack p20 = protocol.load_instrument( 'p20_single_gen2', #instrument definition 'left', #mount position tip_racks=[tips_20]) #assigned tiprack # ============================================================================= # ==========================VARIABLES TO SET#!!!=============================== # ============================================================================= start_vol = 1974 ## The start_vol is the volume (ul) that is in the source labware at ## ## the start of the protocol. ## dispension_vol = 42 ## The dispension_vol is the volume (ul) that needs to be aliquoted ## ## into the destination wells/tubes. ## primer_vol = 3 ## The sample_vol is the volume (ul) of sample added to the PCR ## ## reaction. ## p300.starting_tip = tips_200.well('A1') p20.starting_tip = tips_20.well('A1') ## The starting_tip is the location of first pipette tip in the box ## container = 'tube_5mL' ## The container variable is needed for the volume tracking module. ## ## It tells the module which dimensions to use for the calculations ## ## of the pipette height. It is the source labware from which liquid ## ## is aliquoted. ## ## There are several options to choose from: ## ## 'tube_1.5ml', 'tube_2mL', 'tube_5mL', 'tube_15mL', 'tube_50mL' ## mastermix_source = mastermix_tube['C1'] # Mastermix destination wells================================================== mastermix = [] ## Create an empty list to append wells to ## mastermix_columns = ([ mastermix_strips_1.columns_by_name()[column_name] for column_name in ['2', '7', '11'] ] + [ mastermix_strips_2.columns_by_name()[column_name] for column_name in ['2', '7'] ]) ## Make a list of columns, this is a list of lists! ## for column in mastermix_columns: for well in column: mastermix.append(well) ## Separate the columns into wells and append them to list ## mastermix_wells = ([ mastermix_strips_2.wells_by_name()[well_name] for well_name in ['A11', 'B11'] ]) ## Make a list of separate wells ## for well in mastermix_wells: mastermix.append(well) ## Append the wells to the list ## # Primer source tubes========================================================== primers = [] ## Create an empty list to append wells to ## primer_columns = ([ primer_strips_1.columns_by_name()[column_name] for column_name in ['2', '7', '11'] ] + [ primer_strips_2.columns_by_name()[column_name] for column_name in ['2', '7'] ]) ## Make a list of columns, this is a list of lists! ## for column in primer_columns: for well in column: primers.append(well) ## Separate the columns into wells and append them to list ## primer_wells = ([ primer_strips_2.wells_by_name()[well_name] for well_name in ['A11', 'B11'] ]) ## Make a list of separate wells ## for well in primer_wells: primers.append(well) ## Append the wells to the list ## # ============================================================================= # ============================================================================= # ==========================PREDIFINED VARIABLES=============================== # ============================================================================= aspiration_vol = dispension_vol + (dispension_vol / 100 * 2) ## The aspiration_vol is the volume (ul) that is aspirated from the ## ## container. ## ##### Variables for volume tracking start_height = vt.cal_start_height(container, start_vol) ## Call start height calculation function from volume tracking module.## current_height = start_height ## Set the current height to start height at the beginning of the ## ## protocol. ## # ============================================================================= # ===============================ALIQUOTING MIX================================ # ============================================================================= ## For each column in destination_wells, pick up a tip, than for each ## ## well in these columns pipette mix, and after the+ column drop the tip## ## Repeat untill all columns in the list are done. ## for i, well in enumerate(mastermix): ## Name all the wells in the plate 'well', for all these do: ## if i == 0: p300.pick_up_tip() ## If we are at the first well, start by picking up a tip. ## elif i % 8 == 0: p300.drop_tip() p300.pick_up_tip() ## Then, after every 8th well, drop tip and pick up a new one. ## current_height, pip_height, bottom_reached = vt.volume_tracking( container, dispension_vol, current_height) ## The volume_tracking function needs the arguments container, ## ## dispension_vol, and the current_height which we have set in ## ## this protocol. With those variables, the function updates ## ## the current_height, the pip_height and calculates the ## ## delta_height of the liquid after the next aspiration step. ## if bottom_reached: aspiration_location = mastermix_source.bottom(z=1) #!!! protocol.comment("You've reached the bottom!") else: aspiration_location = mastermix_source.bottom(pip_height) #!!! ## If the level of the liquid in the next run of the loop will ## ## be smaller than 1 we have reached the bottom of the tube. ## ## To prevent the pipette from crashing into the bottom, we ## ## tell it to go home and pause the protocol so that this can ## ## never happen. Set the location of where to aspirate from. ## ## Because we put this in the loop, the location will change ## ## to the newly calculated height after each pipetting step. ## p300.aspirate(aspiration_vol, aspiration_location) ## Aspirate the amount specified in aspiration_vol from the ## ## location specified in aspiration_location. ## p300.dispense(dispension_vol, well) ## Dispense the amount specified in dispension_vol to the ## ## location specified in well (so a new well every time the ## ## loop restarts) ## p300.dispense(10, aspiration_location) ## Alternative for blow-out, make sure the tip doesn't fill ## ## completely when using a disposal volume by dispensing some ## ## of the volume after each pipetting step. (blow-out to many ## ## bubbles) ## p300.drop_tip() # ============================================================================= # ===============================ADDING PRIMERS================================ # ============================================================================= ## For the columns in both the source (primers) and the destination ## ## (mix): loop trough the wells in those columns. # for primer_tube, mix_tube in zip(primers, mastermix): p20.pick_up_tip() p20.aspirate(primer_vol, primer_tube) p20.dispense(primer_vol, mix_tube) primer_mix_vol = primer_vol + 3 ## primer_mix_vol = volume for pipetting up and down ## p20.mix(3, primer_mix_vol, mix_tube) p20.dispense(10, mix_tube) p20.drop_tip()
def run(protocol: protocol_api.ProtocolContext): """ Alliquoting MasterMix Adding samples from 1.5 mL tubes to PCR_strips or plate. different DNA volumes + water to add up """ # ============================================================================= # LOADING LABWARE AND PIPETTES================================================= # ============================================================================= ## For available labware see "labware/list_of_available_labware". ## #pipette tips tips_200 = protocol.load_labware( 'opentrons_96_filtertiprack_200ul', #labware definition 9, #deck position '200tips') #custom name tips_20_1 = protocol.load_labware( 'opentrons_96_filtertiprack_20ul', #labware definition 3, #deck position '20tips_1') #custom name tips_20_2 = protocol.load_labware( 'opentrons_96_filtertiprack_20ul', #labware definition 6, #deck position '20tips_2') #custom name # Tube_racks & plates sample_tubes_1 = protocol.load_labware( 'opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap',#labware def 1, #deck position 'sample_tubes_1') #custom name if sample_racks >= 2: sample_tubes_2 = protocol.load_labware( 'opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap',#labw def 4, #deck pos 'sample_tubes_2') #cust name if sample_racks >= 3: sample_tubes_3 = protocol.load_labware( 'opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap',#labw def 7, #deck pos 'sample_tubes_3') #cust name if sample_racks >= 4: sample_tubes_4 = protocol.load_labware( 'opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap',#labw def 10, #deck pos 'sample_tubes_4') #cust name if PCR_tubes == 'plate_96': PCR_1 = protocol.load_labware( 'biorad_96_wellplate_200ul_pcr', #labware definition 2, #deck position 'plate_96') #custom name if PCR_tubes == 'PCR_strips': ### !!! OPTION 1: ROBOT # PCR_1 = protocol.load_labware( # 'pcrstrips_96_wellplate_200ul', #labware definition # 2, #deck position # 'PCR_tube_1') #custom name # if PCR_racks >= 2: # PCR_2 = protocol.load_labware( # 'pcrstrips_96_wellplate_200ul', #labware definition # 5, #deck position # 'PCR_tube_2') #custom name # if PCR_racks >= 3: # PCR_3 = protocol.load_labware( # 'pcrstrips_96_wellplate_200ul', #labware definition # 8, #deck position # 'PCR_tube_3') #custom name ##### !!! OPTION 2: SIMULATOR with open("labware/pcrstrips_96_wellplate_200ul/" "pcrstrips_96_wellplate_200ul.json") as labware_file: labware_def_pcrstrips = json.load(labware_file) PCR_1 = protocol.load_labware_from_definition( labware_def_pcrstrips, #variable derived from opening json 2, #deck position 'PCR_tube_1') #custom name if PCR_racks >= 2: PCR_2 = protocol.load_labware_from_definition( labware_def_pcrstrips, #variable derived from opening json 5, #deck position 'PCR_tube_2') #custom name if PCR_racks >= 3: PCR_3 = protocol.load_labware_from_definition( labware_def_pcrstrips, #variable derived from opening json 8, #deck position 'PCR_tube_2') #custom name ##### !!! OPTION 1: ROBOT # tubes_5mL = protocol.load_labware( # 'eppendorfscrewcap_15_tuberack_5000ul', #labware def # 11, #deck position # 'tubes_5mL') #custom name ##### !!! OPTION 2: SIMULATOR with open("labware/eppendorfscrewcap_15_tuberack_5000ul/" "eppendorfscrewcap_15_tuberack_5000ul.json") as labware_file: labware_def_5mL = json.load(labware_file) tubes_5mL = protocol.load_labware_from_definition( labware_def_5mL, #variable derived from opening json 11, #deck position 'tubes_5mL') #custom name # Pipettes p20 = protocol.load_instrument( 'p20_single_gen2', #instrument definition 'left', #mount position tip_racks=[tips_20_1, tips_20_2]) #assigned tiprack p300 = protocol.load_instrument( 'p300_single_gen2', #instrument definition 'right', #mount position tip_racks=[tips_200]) #assigned tiprack # ============================================================================= # PREDIFINED VARIABLES========================================================= # ============================================================================= ##### Mastermix aspiration_vol = dispension_vol + (dispension_vol/100*2) ## The aspiration_vol is the volume (ul) that is aspirated from the ## ## container. ## MM_start_height = vt.cal_start_height('tube_5mL', start_vol_MM) ## Call start height calculation function from volume tracking module. ## MM_current_height = MM_start_height ## Set the current height to start height at the beginning of the ## ## protocol. ## ##### Water w_start_height = vt.cal_start_height('tube_5mL', start_vol_w) ## Call start height calculation function from volume tracking module. ## w_current_height = w_start_height ## Set the current height to start height at the beginning of the ## ## protocol. ## # ============================================================================= # SETTING LOCATIONS============================================================ # ============================================================================= ##### Setting starting tip ## p300.starting_tip = tips_200.well(starting_tip_p200) p20.starting_tip = tips_20_1.well(starting_tip_p20) ## The starting_tip is the location of first pipette tip in the box ## # Sample source wells sample_sources = [] ## Create an empty list to append wells to. ## sample_sources = sample_tubes_1.wells() if sample_racks >= 2: sample_sources = sample_sources + sample_tubes_2.wells() if sample_racks >= 3: sample_sources = sample_sources + sample_tubes_3.wells() if sample_racks >= 4: sample_sources = sample_sources + sample_tubes_4.wells() sample_sources = sample_sources[:number_of_samples] # Destination wells sample_destinations = [] ## Create an empty list to append wells to. ## if PCR_tubes == 'plate_96': sample_destinations = PCR_1.wells() elif PCR_tubes == 'PCR_strips': PCR_columns = ( ([PCR_1.columns_by_name()[column_name] for column_name in strip_positions])) if PCR_racks >= 2: PCR_columns_2 = ( ([PCR_2.columns_by_name()[column_name] for column_name in strip_positions])) PCR_columns = PCR_columns + PCR_columns_2 if PCR_racks >= 3: PCR_columns_3 = ( ([PCR_3.columns_by_name()[column_name] for column_name in strip_positions])) PCR_columns = PCR_columns + PCR_columns_3 for column in PCR_columns: for well in column: sample_destinations.append(well) sample_destinations = sample_destinations[:number_of_samples] ##### Tube locations ## MasterMix = tubes_5mL[mastermix_source] ## Location of the 5mL tube with mastermix ## water = tubes_5mL[water_tube] ## Location of the 5mL tube with water ## ## ALIQUOTING MASTERMIX======================================================== ## ============================================================================ for i, well in enumerate(sample_destinations): ## aliquot mix, for each well do the following: ## if i == 0: p300.pick_up_tip() ## If we are at the first well, start by picking up a tip. ## elif i % 16 == 0: p300.drop_tip() p300.pick_up_tip() ## Then, after every 16th well, drop tip and pick up new ## MM_current_height, pip_height, bottom_reached = vt.volume_tracking( 'tube_5mL', dispension_vol, MM_current_height) ## call volume_tracking function, obtain current_height, ## ## pip_height and whether bottom_reached. ## if bottom_reached: aspiration_location = MasterMix.bottom(z=1) protocol.comment("You've reached the bottom of the tube!") ## If bottom is reached keep pipetting from bottom + 1 ## else: aspiration_location = MasterMix.bottom(pip_height) ## Set the location of where to aspirate from. ## #### The actual aliquoting of mastermix ## p300.aspirate(aspiration_vol, aspiration_location) ## Aspirate the amount specified in aspiration_vol from the ## ## location specified in aspiration_location. ## p300.dispense(dispension_vol, well) ## Dispense the amount specified in dispension_vol to the ## ## location specified in well (so a new well every time the ## ## loop restarts) ## p300.dispense(10, aspiration_location) ## Alternative for blow-out, make sure the tip doesn't fill ## ## completely when using a disposal volume by dispensing some ## ## of the volume after each pipetting step. (blow-out to many ## ## bubbles) ## p300.drop_tip() # ============================================================================= # ADDING SAMPLES AND WATER===================================================== # ============================================================================= ## Loop through source and destination wells for sample_tube, well, sample_vol in zip( sample_sources, sample_destinations, DNA_µL_list ): if sample_vol > 0: p20.pick_up_tip() p20.aspirate(sample_vol, sample_tube) p20.dispense(sample_vol, well) sample_mix_vol = sample_vol + 3 ## mix_vol = volume for pipetting up and down ## p20.mix(3, sample_mix_vol, well) p20.dispense(10, well) p20.drop_tip() water_vol = max_DNA_volume - sample_vol ## volume of water needed to add a total of max_DNA_volume if water_vol > 0: w_current_height, pip_height, bottom_reached = vt.volume_tracking( 'tube_5mL', water_vol, w_current_height) ## call volume_tracking function, obtain current_height, ## ## pip_height and whether bottom_reached. ## if bottom_reached: aspiration_location = water.bottom(z=1) protocol.comment("You've reached the bottom of the tube!") ## If bottom is reached keep pipetting from bottom + 1 ## else: aspiration_location = water.bottom(pip_height) ## Set the location of where to aspirate from. ## p20.pick_up_tip() p20.aspirate(water_vol, aspiration_location) p20.dispense(water_vol, well) mix_vol = water_vol + 3 ## mix_vol = volume for pipetting up and down ## p20.mix(3, mix_vol, well) p20.dispense(10, well) p20.drop_tip()
def run(ctx: protocol_api.ProtocolContext): source_plate = ctx.load_labware('nest_96_wellplate_100ul_pcr_full_skirt', '1', 'RNA elution plate from station B') pcr_plate = ctx.load_labware('nest_96_wellplate_100ul_pcr_full_skirt', '2', 'PCR plate') tuberack = ctx.load_labware( 'opentrons_24_tuberack_eppendorf_2ml_safelock_snapcap', '5', '2ml Eppendorf tuberack') tips20 = [ ctx.load_labware('opentrons_96_filtertiprack_20ul', slot) for slot in ['3', '6', '9'] ] # pipette p20 = ctx.load_instrument('p20_single_gen2', 'right', tip_racks=tips20) # setup up sample sources and destinations samples = source_plate.wells()[:NUM_SAMPLES] sample_dest_sets = [ row[i * 3:(i + 1) * 3] for i in range(12 // 3) for row in pcr_plate.rows() ][:NUM_SAMPLES] mm = tuberack.rows()[0][:3] mm_dests = [[well for col in pcr_plate.columns()[j::3] for well in col][:NUM_SAMPLES] + pcr_plate.columns()[9 + j][-2:] for j in range(3)] pos_control = tuberack.rows()[1][0] pos_control_dests = pcr_plate.rows()[-2][-1 * 3:] neg_control = tuberack.rows()[1][1] neg_control_dests = tuberack.rows()[-1][-1 * 3:] # transfer mastermixes for s, d_set in zip(mm, mm_dests): p20.transfer(15, s, d_set) # transfer samples to corresponding locations for s, d_set in zip(samples, sample_dest_sets): for d in d_set: p20.pick_up_tip() p20.transfer(5, s, d, new_tip='never') p20.mix(1, 10, d) p20.blow_out(d.top(-2)) p20.aspirate(5, d.top(2)) p20.drop_tip() # transfer controls for d in pos_control_dests: p20.pick_up_tip() p20.transfer(5, pos_control, d, new_tip='never') p20.mix(1, 10, d) p20.blow_out(d.top(-2)) p20.aspirate(5, d.top(2)) p20.drop_tip() for d in neg_control_dests: p20.pick_up_tip() p20.transfer(5, neg_control, d, new_tip='never') p20.mix(1, 10, d) p20.blow_out(d.top(-2)) p20.aspirate(5, d.top(2)) p20.drop_tip()
def run(protocol: protocol_api.ProtocolContext): """ Adding samples from 1.5 mL tubes or PCR_strips to a 96 wells plate. """ # ============================================================================= # LOADING LABWARE AND PIPETTES================================================= # ============================================================================= ## For available labware see "labware/list_of_available_labware". ## #pipette tips tips_20_1 = protocol.load_labware( 'opentrons_96_filtertiprack_20ul', #labware definition 7, #deck position '20tips_1') #custom name tips_20_2 = protocol.load_labware( 'opentrons_96_filtertiprack_20ul', #labware definition 10, #deck position '20tips_2') #custom name # Tube_racks & plates if sample_tubes == 'tubes_1.5mL': sample_tubes_1 = protocol.load_labware( 'opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap', #labware def 4, #deck position 'sample_tubes_1') #custom name if sample_racks >= 2: sample_tubes_2 = protocol.load_labware( 'opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap', #labw def 1, #deck pos 'sample_tubes_2') #cust name if sample_racks >= 3: sample_tubes_3 = protocol.load_labware( 'opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap', #labw def 3, #deck pos 'sample_tubes_3') #cust name if sample_racks >= 4: sample_tubes_4 = protocol.load_labware( 'opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap', #labw def 11, #deck pos 'sample_tubes_4') #cust name if sample_tubes == 'PCR_strips': ##### !!! OPTION 1: ROBOT sample_strips_1 = protocol.load_labware( 'pcrstrips_96_wellplate_200ul', #labware definition 4, #deck position 'sample_strips_1') #custom name if sample_racks >= 2: sample_strips_2 = protocol.load_labware( 'pcrstrips_96_wellplate_200ul', #labware definition 1, #deck position 'sample_strips_2') #custom name if sample_racks >= 3: sample_strips_3 = protocol.load_labware( 'pcrstrips_96_wellplate_200ul', #labware definition 3, #deck position 'sample_strips_3') #custom name if sample_racks >= 4: sample_strips_4 = protocol.load_labware( 'pcrstrips_96_wellplate_200ul', #labware definition 11, #deck position 'sample_strips_4') #custom name ##### !!! OPTION 2: SIMULATOR # with open("labware/pcrstrips_96_wellplate_200ul/" # "pcrstrips_96_wellplate_200ul.json") as labware_file: # labware_def_pcrstrips = json.load(labware_file) # sample_strips_1 = protocol.load_labware_from_definition( # labware_def_pcrstrips, #variable derived from opening json # 4, #deck position # 'sample_strips_1') #custom name # if sample_racks >= 2: # sample_strips_2 = protocol.load_labware_from_definition( # labware_def_pcrstrips, #variable derived from opening json # 1, #deck position # 'sample_strips_2') #custom name # if sample_racks >= 3: # sample_strips_3 = protocol.load_labware_from_definition( # labware_def_pcrstrips, #variable derived from opening json # 3, #deck position # 'sample_strips_3') #custom name # if sample_racks >= 4: # sample_strips_4 = protocol.load_labware_from_definition( # labware_def_pcrstrips, #variable derived from opening json # 11, #deck position # 'sample_strips_4') #custom name ##### !!! OPTION 1: ROBOT plate_96 = protocol.load_labware( 'biorad_qpcr_plate_eppendorf_cool_rack', #labware definition 5, #deck position '96well_plate_rack') #custom name ##### !!! OPTION 2: SIMULATOR # with open("labware/biorad_qpcr_plate_eppendorf_cool_rack/" # "biorad_qpcr_plate_eppendorf_cool_rack.json") as labware_file: # labware_def_cool_rack = json.load(labware_file) # plate_96 = protocol.load_labware_from_definition( # labware_def_cool_rack, #variable derived from opening json # 5, #deck position # '96well_plate_rack') #custom name # Pipettes p20 = protocol.load_instrument( 'p20_single_gen2', #instrument definition 'left', #mount position tip_racks=[tips_20_1, tips_20_2]) #assigned tiprack # ============================================================================= # PREDIFINED VARIABLES========================================================= # ============================================================================= p20.starting_tip = tips_20_1.well(starting_tip_p20) ## The starting_tip is the location of first pipette tip in the box ## # Sample source wells sample_sources = [] ## Create an empty list to append wells to. ## if sample_tubes == 'tubes_1.5mL': sample_sources = sample_tubes_1.wells() if sample_racks >= 2: sample_sources = sample_sources + sample_tubes_2.wells() if sample_racks >= 3: sample_sources = sample_sources + sample_tubes_3.wells() if sample_racks >= 4: sample_sources = sample_sources + sample_tubes_4.wells() sample_sources = sample_sources[:number_of_samples] if std_sample: std_source = [sample_sources[-1]] * (no_of_std_samples - 1) for well in std_source: sample_sources.append(well) ## adds the same well (where the std_sample is) to the sample ## ## sources list, so will pipete no_of_std_samples times from ## ## the same well ## if sample_tubes == 'PCR_strips': sample_columns = (([ sample_strips_1.columns_by_name()[column_name] for column_name in strip_positions ])) if sample_racks >= 2: sample_columns2 = (([ sample_strips_2.columns_by_name()[column_name] for column_name in strip_positions ])) for column in sample_columns2: sample_columns.append(column) if sample_racks >= 3: sample_columns3 = (([ sample_strips_3.columns_by_name()[column_name] for column_name in strip_positions ])) for column in sample_columns3: sample_columns.append(column) if sample_racks >= 4: sample_columns4 = (([ sample_strips_4.columns_by_name()[column_name] for column_name in strip_positions ])) for column in sample_columns4: sample_columns.append(column) ## Make a list of columns, this is a list of lists! ## for column in sample_columns: for well in column: sample_sources.append(well) sample_sources = sample_sources[:number_of_samples] ## Separate the columns into wells and append them to list ## # ADDING SAMPLES=============================================================== # ============================================================================= ## Loop through source and destination wells for sample_tube, well in zip(sample_sources, plate_96.wells()): p20.pick_up_tip() p20.aspirate(sample_vol, sample_tube) p20.dispense(sample_vol, well) sample_mix_vol = sample_vol + 3 ## primer_mix_vol = volume for pipetting up and down ## p20.mix(3, sample_mix_vol, well) p20.dispense(10, well) p20.drop_tip()
def run(protocol: protocol_api.ProtocolContext): tiprack = protocol.load_labware(TIPRACK_LOADNAME, TIPRACK_SLOT) pipette = protocol.load_instrument( PIPETTE_NAME, PIPETTE_MOUNT, tip_racks=[tiprack]) test_labware = protocol.load_labware_from_definition( LABWARE_DEF, TEST_LABWARE_SLOT, LABWARE_LABEL, ) num_cols = len(LABWARE_DEF.get('ordering', [[]])) num_rows = len(LABWARE_DEF.get('ordering', [[]])[0]) well_locs = uniq([ 'A1', '{}{}'.format(chr(ord('A') + num_rows - 1), str(num_cols))]) pipette.pick_up_tip() def set_speeds(rate): protocol.max_speeds.update({ 'X': (600 * rate), 'Y': (400 * rate), 'Z': (125 * rate), 'A': (125 * rate), }) speed_max = max(protocol.max_speeds.values()) for instr in protocol.loaded_instruments.values(): instr.default_speed = speed_max set_speeds(RATE) for slot in CALIBRATION_CROSS_SLOTS: coordinate = CALIBRATION_CROSS_COORDS[slot] location = types.Location(point=types.Point(**coordinate), labware=None) pipette.move_to(location) protocol.pause( f"Confirm {PIPETTE_MOUNT} pipette is at slot {slot} calibration cross") pipette.home() protocol.pause(f"Place your labware in Slot {TEST_LABWARE_SLOT}") for well_loc in well_locs: well = test_labware.well(well_loc) all_4_edges = [ [well._from_center_cartesian(x=-1, y=0, z=1), 'left'], [well._from_center_cartesian(x=1, y=0, z=1), 'right'], [well._from_center_cartesian(x=0, y=-1, z=1), 'front'], [well._from_center_cartesian(x=0, y=1, z=1), 'back'] ] set_speeds(RATE) pipette.move_to(well.top()) protocol.pause("Moved to the top of the well") for edge_pos, edge_name in all_4_edges: set_speeds(SLOWER_RATE) edge_location = types.Location(point=edge_pos, labware=None) pipette.move_to(edge_location) protocol.pause(f'Moved to {edge_name} edge') # go to bottom last. (If there is more than one well, use the last well first # because the pipette is already at the last well at this point) for well_loc in reversed(well_locs): well = test_labware.well(well_loc) set_speeds(RATE) pipette.move_to(well.bottom()) protocol.pause("Moved to the bottom of the well") pipette.blow_out(well) set_speeds(1.0) pipette.return_tip()
def run(ctx: protocol_api.ProtocolContext): global MM_TYPE # check source (elution) labware type source_plate = ctx.load_labware( 'opentrons_96_aluminumblock_nest_wellplate_100ul', '1', 'chilled elution plate on block from Station B') tips20 = [ ctx.load_labware('opentrons_96_filtertiprack_20ul', slot) for slot in ['3', '6', '7', '8', '9', '10', '11'] ] tips300 = [ctx.load_labware('opentrons_96_filtertiprack_200ul', '2')] tempdeck = ctx.load_module('Temperature Module Gen2', '4') pcr_plate = tempdeck.load_labware( 'opentrons_96_aluminumblock_nest_wellplate_100ul', 'PCR plate') tempdeck.set_temperature(4) tube_block = ctx.load_labware( 'opentrons_24_aluminumblock_nest_2ml_screwcap', '5', '2ml screw tube aluminum block for mastermix + controls') # pipette p20 = ctx.load_instrument('p20_single_gen2', 'right', tip_racks=tips20) p300 = ctx.load_instrument('p300_single_gen2', 'left', tip_racks=tips300) p300.flow_rate.aspirate = 20 # setup up sample sources and destinations sources = source_plate.wells()[:NUM_SAMPLES] sample_dests = pcr_plate.wells()[:NUM_SAMPLES] tip_log = {'count': {}} folder_path = '/data/C' tip_file_path = folder_path + '/tip_log.json' if TIP_TRACK and not ctx.is_simulating(): if os.path.isfile(tip_file_path): with open(tip_file_path) as json_file: data = json.load(json_file) if 'tips20' in data: tip_log['count'][p20] = data['tips20'] else: tip_log['count'][p20] = 0 if 'tips300' in data: tip_log['count'][p300] = data['tips300'] else: tip_log['count'][p300] = 0 else: tip_log['count'] = {p20: 0, p300: 0} else: tip_log['count'] = {p20: 0, p300: 0} tip_log['tips'] = { p20: [tip for rack in tips20 for tip in rack.wells()], p300: [tip for rack in tips300 for tip in rack.wells()] } tip_log['max'] = {pip: len(tip_log['tips'][pip]) for pip in [p20, p300]} def pick_up(pip): nonlocal tip_log if tip_log['count'][pip] == tip_log['max'][pip]: ctx.pause('Replace ' + str(pip.max_volume) + 'µl tipracks before \ resuming.') pip.reset_tipracks() tip_log['count'][pip] = 0 pip.pick_up_tip(tip_log['tips'][pip][tip_log['count'][pip]]) tip_log['count'][pip] += 1 """ mastermix component maps """ mm_tube = tube_block.wells()[0] mm_dict = { 'volume': 15, 'components': { tube: vol for tube, vol in zip(tube_block.columns()[1][:3], [6.25, 1.25, 7.5]) } } vol_overage = 1.2 if NUM_SAMPLES > 48 else 1.1 # decrease overage for small sample number total_mm_vol = mm_dict['volume'] * (NUM_SAMPLES + 2) * vol_overage # translate total mastermix volume to starting height r = mm_tube.diameter / 2 mm_height = total_mm_vol / (math.pi * (r**2)) - 5 def h_track(vol): nonlocal mm_height dh = 1.1 * vol / (math.pi * (r**2)) # compensate for 10% theoretical volume loss mm_height = mm_height - dh if mm_height - dh > 2 else 2 # stop at 2mm above mm tube bottom return mm_tube.bottom(mm_height) if PREPARE_MASTERMIX: for i, (tube, vol) in enumerate(mm_dict['components'].items()): comp_vol = vol * (NUM_SAMPLES + 2) * vol_overage pip = p300 if comp_vol > 20 else p20 pick_up(pip) num_trans = math.ceil(comp_vol / 160) vol_per_trans = comp_vol / num_trans for _ in range(num_trans): pip.air_gap(20) pip.aspirate(vol_per_trans, tube) ctx.delay(seconds=3) pip.touch_tip(tube) pip.air_gap(20) pip.dispense(20, mm_tube.top()) # void air gap pip.dispense(vol_per_trans, mm_tube.bottom(2)) pip.dispense(20, mm_tube.top()) # void pre-loaded air gap pip.blow_out(mm_tube.top()) pip.touch_tip(mm_tube) if i < len( mm_dict['components'].items() ) - 1 or pip == p20: # only keep tip if last component and p300 in use pip.drop_tip() mm_total_vol = mm_dict['volume'] * (NUM_SAMPLES + 2) * vol_overage if not p300.hw_pipette[ 'has_tip']: # pickup tip with P300 if necessary for mixing pick_up(p300) mix_vol = mm_total_vol / 2 if mm_total_vol / 2 <= 200 else 200 # mix volume is 1/2 MM total, maxing at 200µl mix_loc = mm_tube.bottom(20) if NUM_SAMPLES > 48 else mm_tube.bottom(5) p300.mix(7, mix_vol, mix_loc) p300.blow_out(mm_tube.top()) p300.touch_tip() p300.drop_tip() # transfer mastermix to TD plate mm_vol = mm_dict['volume'] pick_up(p20) for d in sample_dests: p20.air_gap(20 - mm_vol) p20.aspirate(mm_vol, mm_tube) p20.dispense(20, d) p20.drop_tip() # transfer samples to corresponding locations for s, d in zip(sources, sample_dests): pick_up(p20) p20.air_gap(10) p20.aspirate(SAMPLE_VOL, s.bottom(2)) p20.air_gap(2) p20.dispense(2, d.top()) # void air gap p20.dispense(10 + SAMPLE_VOL, d.bottom(2)) p20.mix(1, 10, d.bottom(2)) p20.blow_out(d.top(-2)) p20.aspirate( 5, d.top(2)) # suck in any remaining droplets on way to trash p20.drop_tip() # transfer positive and negative control pos_control = tube_block.wells()[1] neg_control = tube_block.wells()[2] for s, d in zip([pos_control, neg_control], pcr_plate.wells()[NUM_SAMPLES:NUM_SAMPLES + 2]): pick_up(p20) p20.air_gap(10) p20.aspirate(SAMPLE_VOL, s.bottom(2)) p20.air_gap(2) p20.dispense(2, d.top()) # void air gap p20.dispense(10 + SAMPLE_VOL, d.bottom(2)) p20.mix(1, 10, d.bottom(2)) p20.blow_out(d.top(-2)) p20.aspirate( 5, d.top(2)) # suck in any remaining droplets on way to trash p20.drop_tip() # track final used tip if TIP_TRACK and not ctx.is_simulating(): if not os.path.isdir(folder_path): os.mkdir(folder_path) data = { 'tips20': tip_log['count'][p20], 'tips300': tip_log['count'][p300] } with open(tip_file_path, 'w') as outfile: json.dump(data, outfile)
def run(ctx: protocol_api.ProtocolContext): # Define the STEPS of the protocol STEP = 0 STEPS = { # Dictionary with STEP activation, description, and times 1: {'Execute': True, 'description': 'Add samples (300ul)'}, } for s in STEPS: # Create an empty wait_time if 'wait_time' not in STEPS[s]: STEPS[s]['wait_time'] = 0 if not ctx.is_simulating(): # Folder and file_path for log time folder_path = '/var/lib/jupyter/notebooks/'+run_id if not os.path.isdir(folder_path): os.mkdir(folder_path) file_path = folder_path + '/KA_SampleSetup_pathogen_time_log.txt' # Define Reagents as objects with their properties class Reagent: def __init__(self, name, flow_rate_aspirate, flow_rate_dispense, rinse, reagent_reservoir_volume, delay, num_wells, h_cono, v_fondo, tip_recycling = 'none'): self.name = name self.flow_rate_aspirate = flow_rate_aspirate self.flow_rate_dispense = flow_rate_dispense self.rinse = bool(rinse) self.reagent_reservoir_volume = reagent_reservoir_volume self.delay = delay self.num_wells = num_wells self.col = 0 self.vol_well = 0 self.h_cono = h_cono self.v_cono = v_fondo self.unused=[] self.tip_recycling = tip_recycling self.vol_well_original = reagent_reservoir_volume / num_wells Samples = Reagent(name = 'Samples', flow_rate_aspirate = 1, flow_rate_dispense = 1, rinse = False, delay = 0, reagent_reservoir_volume = 700 * 24, num_wells = 24, # num_cols comes from available columns h_cono = 4, v_fondo = 4 * math.pi * 4**3 / 3 ) # Sphere Samples.vol_well = 700 ################## # Custom functions def generate_source_table(source): ''' Concatenate the wells from the different origin racks ''' for rack_number in range(len(source)): if rack_number == 0: s = source[rack_number].wells() else: s = s + source[rack_number].wells() return s 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 = -5)) if touch_tip == True: pipet.touch_tip(speed = 20, v_offset = -5, radius = 0.9) 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 calc_height(reagent, cross_section_area, aspirate_volume, min_height = 0.5): nonlocal ctx ctx.comment('Remaining volume ' + str(reagent.vol_well) + '< needed volume ' + str(aspirate_volume) + '?') if reagent.vol_well < aspirate_volume: reagent.unused.append(reagent.vol_well) ctx.comment('Next column should be picked') ctx.comment('Previous to change: ' + str(reagent.col)) # column selector position; intialize to required number reagent.col = reagent.col + 1 ctx.comment(str('After change: ' + str(reagent.col))) reagent.vol_well = reagent.vol_well_original ctx.comment('New volume:' + str(reagent.vol_well)) height = (reagent.vol_well - aspirate_volume - reagent.v_cono) / cross_section_area #- reagent.h_cono reagent.vol_well = reagent.vol_well - aspirate_volume ctx.comment('Remaining volume:' + str(reagent.vol_well)) if height < min_height: height = min_height col_change = True else: height = (reagent.vol_well - aspirate_volume - reagent.v_cono) / cross_section_area #- reagent.h_cono reagent.vol_well = reagent.vol_well - aspirate_volume ctx.comment('Calculated height is ' + str(height)) if height < min_height: height = min_height ctx.comment('Used height is ' + str(height)) col_change = False return height, col_change ########## # pick up tip and if there is none left, prompt user for a new rack def pick_up(pip): nonlocal tip_track if not ctx.is_simulating(): if tip_track['counts'][pip] == tip_track['maxes'][pip]: ctx.pause('Replace ' + str(pip.max_volume) + 'µl tipracks before \ resuming.') pip.reset_tipracks() tip_track['counts'][pip] = 0 pip.pick_up_tip() #################################### # load labware and modules #################################### # Load Sample racks if NUM_SAMPLES < 96: rack_num = math.ceil(NUM_SAMPLES / 24) ctx.comment('Used source racks are ' + str(rack_num)) samples_last_rack = NUM_SAMPLES - rack_num * 24 else: rack_num = 4 source_racks = [ctx.load_labware( 'opentrons_24_tuberack_generic_2ml_screwcap', slot, 'source tuberack with screwcap' + str(i + 1)) for i, slot in enumerate(['4', '1', '6', '3'][:rack_num]) ] ################################## # Destination plate dest_plate = ctx.load_labware( 'kf_96_wellplate_2400ul', '5', 'KF 96well destination plate') #################################### # Load tip_racks # tips20 = [ctx.load_labware('opentrons_96_filtertiprack_20ul', slot, '20µl filter tiprack') # for slot in ['2', '8']] tips1000 = [ctx.load_labware('opentrons_96_filtertiprack_1000ul', slot, '1000µl filter tiprack') for slot in ['7', '10']] ################################################################################ # Declare which reagents are in each reservoir as well as deepwell and elution plate # setup samples and destinations sample_sources_full = generate_source_table(source_racks) sample_sources = sample_sources_full[:NUM_SAMPLES] destinations = dest_plate.wells()[:NUM_SAMPLES] # p20 = ctx.load_instrument( # 'p20_single_gen2', mount='right', tip_racks=tips20) p1000 = ctx.load_instrument( 'p1000_single_gen2', 'left', tip_racks=tips1000) # load P1000 pipette # used tip counter and set maximum tips available tip_track = { 'counts': {p1000: 0}, # p1000: 0}, 'maxes': {p1000: len(tips1000) * 96} # ,p20: len(tips20)*96, } ############################################################################ # STEP 1: Add Samples ############################################################################ STEP += 1 if STEPS[STEP]['Execute'] == True: ctx.comment('Step ' + str(STEP) + ': ' + STEPS[STEP]['description']) ctx.comment('###############################################') # Transfer parameters start = datetime.now() for s, d in zip(sample_sources, destinations): if not p1000.hw_pipette['has_tip']: pick_up(p1000) # Mix the sample BEFORE dispensing #custom_mix(p1000, reagent = Samples, location = s, vol = volume_sample, rounds = 2, blow_out = True, mix_height = 15) move_vol_multichannel(p1000, reagent = Samples, source = s, dest = d, vol=volume_sample, air_gap_vol = air_gap_vol, x_offset = x_offset, pickup_height = 1, rinse = Samples.rinse, disp_height = -10, blow_out = True, touch_tip = True) # Mix the sample AFTER dispensing #custom_mix(p1000, reagent = Samples, location = d, vol = volume_sample, rounds = 2, blow_out = True, mix_height = 15) # Drop tip and update counter p1000.drop_tip() tip_track['counts'][p1000] += 1 # Time statistics end = datetime.now() time_taken = (end - start) ctx.comment('Step ' + str(STEP) + ': ' + STEPS[STEP]['description'] + ' took ' + str(time_taken)) STEPS[STEP]['Time:'] = str(time_taken) # Export the time log to a tsv file if not ctx.is_simulating(): with open(file_path, 'w') as f: f.write('STEP\texecution\tdescription\twait_time\texecution_time\n') for key in STEPS.keys(): row = str(key) for key2 in STEPS[key].keys(): row += '\t' + format(STEPS[key][key2]) f.write(row + '\n') f.close() ############################################################################ # Light flash end of program from opentrons.drivers.rpi_drivers import gpio for i in range(3): gpio.set_rail_lights(False) gpio.set_button_light(1, 0, 0) time.sleep(0.3) gpio.set_rail_lights(True) gpio.set_button_light(0, 0, 1) time.sleep(0.3) gpio.set_button_light(0, 1, 0) ctx.comment( 'Finished! \nMove deepwell plate (slot 5) to Station C for MMIX addition and qPCR preparation.') ctx.comment('Used p1000 tips in total: ' + str(tip_track['counts'][p1000])) ctx.comment('Used p1000 racks in total: ' + str(tip_track['counts'][p1000] / 96))
def run(protocol: protocol_api.ProtocolContext): """Function to handle the aliquoting of Illumina primers.""" # Loading labware strips = protocol.load_labware('biorad_96_wellplate_200ul_pcr', 3, '96plate') tiprack_1 = protocol.load_labware('opentrons_96_tiprack_300ul', 9, '300tips_1') f_primers_1 = protocol.load_labware( 'opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap', 1, 'Fprimers_1') f_primers_2 = protocol.load_labware( 'opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap', 4, 'Fprimers_2') r_primers_1 = protocol.load_labware( 'opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap', 7, 'Rprimers_1') r_primers_2 = protocol.load_labware( 'opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap', 10, 'Rprimers_2') # Load pipette p300 = protocol.load_instrument('p300_single_gen2', 'right', tip_racks=[tiprack_1]) # Define functions for transferring. def transfer_f(): "Transfer the forward primers to the strips." # Strip 1 F p300.transfer(20, [ f_primers_1.columns_by_name()[column_name] for column_name in ['1', '2'] ], strips.columns_by_name()['1'], new_tip='always') # Strip 2 F p300.transfer(20, [ f_primers_1.columns_by_name()[column_name] for column_name in ['3', '4'] ], strips.columns_by_name()['4'], new_tip='always') # Strip 3 F p300.transfer(20, [ f_primers_1.columns_by_name()[column_name] for column_name in ['5', '6'] ], strips.columns_by_name()['7'], new_tip='always') # Strip 4 F p300.transfer(20, [ f_primers_2.columns_by_name()[column_name] for column_name in ['1', '2'] ], strips.columns_by_name()['10'], new_tip='always') def transfer_r(): "Transfer the reverse primers to the strips." # Strip 1 R p300.transfer(20, [ r_primers_1.columns_by_name()[column_name] for column_name in ['1', '2'] ], strips.columns_by_name()['1'], new_tip='always') # Strip 2 R p300.transfer(20, [ r_primers_1.columns_by_name()[column_name] for column_name in ['3', '4'] ], strips.columns_by_name()['4'], new_tip='always') # Strip 3 R p300.transfer(20, [ r_primers_1.columns_by_name()[column_name] for column_name in ['5', '6'] ], strips.columns_by_name()['7'], new_tip='always') # Strip 4 R p300.transfer(20, [ r_primers_2.columns_by_name()[column_name] for column_name in ['1', '2'] ], strips.columns_by_name()['10'], new_tip='always') # Numbers of forward primers are used because reverse primers differ per # aliquot. # 1 to 63 transfer_f() transfer_r() protocol.pause('Change the tubes and strips.') # 65 to 127 transfer_f() transfer_r() protocol.pause('Change the tubes and strips.') # 129 to 191 transfer_f() transfer_r() protocol.pause('Change the tubes and strips.') # 193 to 255 transfer_f() transfer_r() protocol.pause('Change the tubes and strips.')