diff --git a/protoBuilds/052d03/tc.ot2.apiv2.py.json b/protoBuilds/052d03/tc.ot2.apiv2.py.json index 74e49fc8a..870fd22fa 100644 --- a/protoBuilds/052d03/tc.ot2.apiv2.py.json +++ b/protoBuilds/052d03/tc.ot2.apiv2.py.json @@ -1,5 +1,5 @@ { - "content": "import math\nfrom opentrons import protocol_api\nfrom opentrons.types import Point\n\nmetadata = {\n 'apiLevel': '2.14',\n 'protocolName': 'Custom Dilution and PCR',\n 'author': 'Nick Diehl '\n}\n\nDO_THERMOCYCLER = True\n\n\ndef run(ctx):\n\n [num_samples, cp_list, type_molecule,\n type_sample_rack] = get_values( # noqa: F821\n 'num_samples', 'cp_list', 'type_molecule', 'type_sample_rack')\n\n # [num_samples, cp_list, type_molecule] = [24, cp_list_ex, 'pDNA']\n\n # parse\n data = [\n [val.strip().upper() for val in line.split(',')]\n for line in cp_list.splitlines()\n if line and line.split(',')[0].strip()]\n\n num_cols = math.ceil((num_samples)/8)\n try:\n tc = ctx.load_module('thermocyclerModuleV2')\n except: # noqa\n tc = ctx.load_module('thermocycler')\n tc.open_lid()\n tc_plate = tc.load_labware('biorad_96_wellplate_200ul_pcr')\n tipracks300 = [\n ctx.load_labware('opentrons_96_tiprack_300ul', slot)\n for slot in ['3']]\n tipracks20 = [\n ctx.load_labware('opentrons_96_tiprack_20ul', slot)\n for slot in ['6', '9']]\n dil_plate = ctx.load_labware('biorad_96_wellplate_200ul_pcr',\n '5', 'dilution plate')\n res = ctx.load_labware('nest_12_reservoir_15ml', '2')\n tuberack = ctx.load_labware(type_sample_rack, '4')\n mm_plate = ctx.load_labware('biorad_96_aluminumblock_250ul', '1',\n 'mastermix plate')\n\n m300 = ctx.load_instrument(\n 'p300_multi_gen2', 'left', tip_racks=tipracks300)\n p20 = ctx.load_instrument(\n 'p20_single_gen2', 'right', tip_racks=tipracks20)\n\n samples = tuberack.wells()[:num_samples]\n pc = tuberack.wells()[num_samples]\n rxn_mix_1 = res.wells()[0]\n rxn_mix_2 = res.wells()[1]\n diluent = res.wells()[2:6]\n mm = res.wells()[5]\n\n if type_molecule == '401':\n vol_rxn_mix_2 = 50.0\n elif type_molecule == 'pDNA':\n vol_rxn_mix_2 = 90.0\n\n # define liquids\n try:\n rxn_mix_1_liq = ctx.define_liquid(\n name='DNAse',\n description='DNAse',\n display_color='#00FF00',\n )\n rxn_mix_2_liq = ctx.define_liquid(\n name='PK',\n description='PK',\n display_color='#0000FF',\n )\n diluent_liq = ctx.define_liquid(\n name='dilution buffer',\n description='dilution buffer',\n display_color='#FF0000',\n )\n mastermix_liq = ctx.define_liquid(\n name='mastermix',\n description='mastermix',\n display_color='#FBFF00',\n )\n sample_liq = ctx.define_liquid(\n name='sample',\n description='sample, NTC, and DAC',\n display_color='#F300FF',\n )\n pc_liq = ctx.define_liquid(\n name='positive control',\n description='diluted 1:100',\n display_color='#050F5D',\n )\n\n # load liquids\n [s.load_liquid(sample_liq, volume=200/num_samples) for s in samples]\n pc.load_liquid(pc_liq, volume=200)\n if not type_molecule == 'pDNA':\n rxn_mix_1.load_liquid(rxn_mix_1_liq, volume=30*num_cols*8*1.1+2000)\n if not type_molecule == '101':\n rxn_mix_2.load_liquid(\n rxn_mix_2_liq, volume=vol_rxn_mix_2*num_cols*8*1.1+2000)\n mm.load_liquid(mastermix_liq, volume=16.5*len(data)*4*1.1+2000)\n [d.load_liquid(diluent_liq, volume=1200)\n for d in diluent[:math.ceil(num_cols*4/3)]]\n\n except: # noqa\n pass\n\n def pick_up(pip):\n try:\n pip.pick_up_tip()\n except protocol_api.labware.OutOfTipsError:\n ctx.pause('Replace the tips')\n pip.reset_tipracks()\n pip.pick_up_tip()\n\n vol_max_dil = 0.8*diluent[0].max_volume\n vol_current = 0\n dil_tracker = iter(diluent)\n dil_current = next(dil_tracker)\n\n def track_dilution(vol):\n nonlocal vol_current\n nonlocal dil_current\n vol_actual = vol*8 # multi-channel pipette\n if vol_actual + vol_current > vol_max_dil:\n vol_current = 0\n dil_current = next(dil_tracker)\n vol_current += vol_actual\n return dil_current\n\n def wick(pip, well, side=1):\n if well.diameter:\n radius = well.diameter/2\n else:\n radius = well.width/2\n pip.move_to(well.bottom().move(Point(x=side*radius*0.7, z=3)))\n\n def slow_withdraw(pip, well, delay=2.0):\n pip.default_speed /= 16\n ctx.delay(seconds=delay)\n pip.move_to(well.top())\n pip.default_speed *= 16\n\n rxn_mix_1_dests = [tc_plate.rows()[0][i*4+1] for i in range(num_cols)]\n if not type_molecule == 'pDNA':\n # first dilution\n first_dil_dests_m = [tc_plate.rows()[0][i*4] for i in range(num_cols)]\n pick_up(m300)\n vol_dil = 180\n for d in first_dil_dests_m:\n source = track_dilution(vol_dil)\n m300.aspirate(vol_dil, source)\n slow_withdraw(m300, source)\n m300.dispense(vol_dil, d.bottom(5))\n slow_withdraw(m300, d)\n m300.drop_tip()\n\n pick_up(m300)\n for d in rxn_mix_1_dests:\n m300.aspirate(30, rxn_mix_1)\n slow_withdraw(m300, rxn_mix_1)\n m300.dispense(30, d.bottom(2))\n slow_withdraw(m300, d)\n m300.drop_tip()\n\n # transfer sample\n first_dil_cols = [tc_plate.columns()[i*4] for i in range(num_cols)]\n first_dil_dests_s = [\n well for col in first_dil_cols for well in col][:num_samples]\n for i, (s, d) in enumerate(zip(samples, first_dil_dests_s)):\n pick_up(p20)\n p20.aspirate(20, s.bottom(0.5))\n slow_withdraw(p20, s)\n p20.dispense(20, d.bottom(d.depth/2))\n # p20.mix(5, 20, d.bottom(d.depth/2))\n slow_withdraw(p20, d)\n if i % 8 == 0: # row A\n p20.move_to(d.top(2))\n p20.move_to(d.top().move(Point(y=-5, z=2)))\n p20.drop_tip()\n\n # add to mix\n for s, d in zip(first_dil_dests_m, rxn_mix_1_dests):\n pick_up(m300)\n m300.mix(5, 100, s.bottom(s.depth/2))\n m300.aspirate(20, s.bottom(5))\n slow_withdraw(m300, s)\n m300.dispense(20, d.bottom(2))\n m300.mix(5, 20, d.bottom(2))\n slow_withdraw(m300, d)\n m300.drop_tip()\n\n tc.close_lid()\n if DO_THERMOCYCLER:\n tc.set_lid_temperature(105)\n tc.set_block_temperature(37, hold_time_minutes=30)\n tc.open_lid()\n\n else:\n # rxn mix 2\n for d in rxn_mix_1_dests:\n\n pick_up(m300)\n m300.aspirate(vol_rxn_mix_2, rxn_mix_2)\n slow_withdraw(m300, rxn_mix_2)\n m300.dispense(vol_rxn_mix_2, d.bottom(2))\n # m300.mix(5, 20, d.bottom(d.depth/2))\n slow_withdraw(m300, d)\n m300.drop_tip()\n rxn_mix_1_columns = [\n tc_plate.columns()[tc_plate.rows()[0].index(col)]\n for col in rxn_mix_1_dests]\n rxn_mix_1_s = [\n well for col in rxn_mix_1_columns for well in col][:num_samples]\n for s, d in zip(samples, rxn_mix_1_s):\n pick_up(p20)\n p20.aspirate(10, s.bottom(0.5))\n slow_withdraw(p20, s)\n p20.dispense(10, d.top(-5))\n p20.mix(5, 20, d.bottom(d.depth/2))\n slow_withdraw(p20, d)\n p20.drop_tip()\n\n if not type_molecule == '101':\n if type_molecule == '401': # rxn mix 2\n for d in rxn_mix_1_dests:\n pick_up(m300)\n m300.aspirate(50, rxn_mix_2)\n slow_withdraw(m300, rxn_mix_2)\n m300.dispense(50, d.bottom(2))\n m300.mix(5, 20, d.bottom(2), rate=0.5)\n slow_withdraw(m300, d)\n m300.drop_tip()\n\n tc.close_lid()\n if DO_THERMOCYCLER:\n tc.set_block_temperature(55, hold_time_minutes=30)\n tc.set_block_temperature(95, hold_time_minutes=15)\n tc.set_block_temperature(4)\n tc.open_lid()\n tc.deactivate_lid()\n\n dil_sets_tc = [\n tc_plate.rows()[0][i*4+2:i*4+4] for i in range(num_cols)\n ]\n dil_sets_dil = [\n dil_plate.rows()[0][i*4:i*4+4] for i in range(num_cols)\n ]\n dil_sets_all = []\n for set_t, set_d in zip(dil_sets_tc, dil_sets_dil):\n dil_set = set_t + set_d\n dil_sets_all.append(dil_set)\n\n # add diluent to all\n pick_up(m300)\n vol_dil = 180\n for d_set in dil_sets_all:\n for d in d_set:\n source = track_dilution(vol_dil)\n m300.aspirate(vol_dil, source)\n slow_withdraw(m300, source)\n m300.dispense(vol_dil, d.bottom(5))\n slow_withdraw(m300, d)\n\n # perform dilutions\n for i, dil_set in enumerate(dil_sets_all):\n sources = [rxn_mix_1_dests[i]] + dil_set[:len(dil_sets_all[0])-1]\n dests = dil_set\n for s, d in zip(sources, dests):\n if not m300.has_tip:\n pick_up(m300)\n m300.aspirate(20, s.bottom(5))\n slow_withdraw(m300, s)\n m300.dispense(20, d.bottom(d.depth/2))\n m300.mix(5, 50, d.bottom(d.depth/2))\n slow_withdraw(m300, d)\n m300.drop_tip()\n\n # mm\n mm_dest_sets = [\n mm_plate.rows()[i % 8][(i//8)*4:(i//8 + 1)*4]\n for i in range(len(data)+1)]\n pick_up(p20)\n for d_set in mm_dest_sets:\n for d in d_set:\n p20.aspirate(2, mm.top()) # pre-airgap\n p20.aspirate(16.5, mm)\n slow_withdraw(p20, mm)\n p20.dispense(p20.current_volume, d.bottom(1))\n slow_withdraw(p20, d)\n p20.drop_tip()\n\n # add diluted positive control\n pc_mm_dest_set = mm_dest_sets.pop(2)\n pick_up(p20)\n for d in pc_mm_dest_set:\n if not p20.has_tip:\n pick_up(p20)\n p20.aspirate(2, pc.top()) # pre-airgap\n p20.aspirate(5.5, pc.bottom(0.5))\n slow_withdraw(p20, pc)\n p20.dispense(p20.current_volume, d.bottom(2))\n slow_withdraw(p20, d)\n p20.drop_tip()\n\n # cherrypick\n cp_lw_map = {\n 'T': tc_plate,\n 'D': dil_plate\n }\n cp_sources = [\n cp_lw_map[line[1][0]].wells_by_name()[line[0]]\n for line in data]\n for s, d_set in zip(cp_sources, mm_dest_sets):\n for d in d_set:\n pick_up(p20)\n p20.aspirate(2, s.top()) # pre-airgap\n p20.aspirate(5.5, s.bottom(5))\n slow_withdraw(p20, s)\n p20.dispense(p20.current_volume, d.bottom(2))\n slow_withdraw(p20, d)\n p20.drop_tip()\n\n # fill remaining columns if necessary\n num_mm_dest_sets = len(data) + 1 # including PC\n if num_mm_dest_sets % 8 == 0:\n remaining_rows = 0\n else:\n remaining_rows = 8 - num_mm_dest_sets % 8\n mm_dest_sets_blank = [\n mm_plate.rows()[i % 8][(i//8)*4:(i//8 + 1)*4]\n for i in range(num_mm_dest_sets, num_mm_dest_sets+remaining_rows)]\n vol_blank = 22.0\n tip_ref_vol = p20.tip_racks[0].wells()[0].max_volume - 2.0 # vol preairgap\n num_trans = math.ceil(vol_blank/tip_ref_vol)\n vol_per_trans = round(vol_blank/num_trans, 2)\n pick_up(p20)\n for dest_set in mm_dest_sets_blank:\n for d in dest_set:\n for _ in range(num_trans):\n source = track_dilution(vol_per_trans)\n p20.aspirate(2, source.top()) # pre-airgap\n p20.aspirate(vol_per_trans, source)\n slow_withdraw(p20, source)\n p20.dispense(p20.current_volume, d.bottom(2))\n slow_withdraw(p20, d)\n p20.drop_tip()\n\n tc.deactivate_block()\n", + "content": "import math\nfrom opentrons import protocol_api\nfrom opentrons.types import Point\n\nmetadata = {\n 'apiLevel': '2.14',\n 'protocolName': 'Custom Dilution and PCR',\n 'author': 'Nick Diehl '\n}\n\nDO_THERMOCYCLER = True\n\n\ndef run(ctx):\n\n [num_samples, cp_list, type_molecule,\n type_sample_rack] = get_values( # noqa: F821\n 'num_samples', 'cp_list', 'type_molecule', 'type_sample_rack')\n\n # [num_samples, cp_list, type_molecule] = [24, cp_list_ex, 'pDNA']\n\n # parse\n data = [\n [val.strip().upper() for val in line.split(',')]\n for line in cp_list.splitlines()\n if line and line.split(',')[0].strip()]\n\n num_cols = math.ceil((num_samples)/8)\n try:\n tc = ctx.load_module('thermocyclerModuleV2')\n except: # noqa\n tc = ctx.load_module('thermocycler')\n tc.open_lid()\n tc_plate = tc.load_labware('biorad_96_wellplate_200ul_pcr')\n tipracks300 = [\n ctx.load_labware('opentrons_96_tiprack_300ul', slot)\n for slot in ['3']]\n tipracks20 = [\n ctx.load_labware('opentrons_96_tiprack_20ul', slot)\n for slot in ['6', '9']]\n dil_plate = ctx.load_labware('biorad_96_wellplate_200ul_pcr',\n '5', 'dilution plate')\n res = ctx.load_labware('nest_12_reservoir_15ml', '2')\n tuberack = ctx.load_labware(type_sample_rack, '4')\n mm_plate = ctx.load_labware('biorad_96_aluminumblock_250ul', '1',\n 'mastermix plate')\n\n m300 = ctx.load_instrument(\n 'p300_multi_gen2', 'left', tip_racks=tipracks300)\n p20 = ctx.load_instrument(\n 'p20_single_gen2', 'right', tip_racks=tipracks20)\n\n samples = tuberack.wells()[:num_samples]\n pc = tuberack.wells()[num_samples]\n rxn_mix_1 = res.wells()[0]\n rxn_mix_2 = res.wells()[1]\n diluent = res.wells()[2:6]\n mm = res.wells()[5]\n\n if type_molecule == '401':\n vol_rxn_mix_2 = 50.0\n elif type_molecule == 'pDNA':\n vol_rxn_mix_2 = 90.0\n\n # define liquids\n try:\n rxn_mix_1_liq = ctx.define_liquid(\n name='DNAse',\n description='DNAse',\n display_color='#00FF00',\n )\n rxn_mix_2_liq = ctx.define_liquid(\n name='PK',\n description='PK',\n display_color='#0000FF',\n )\n diluent_liq = ctx.define_liquid(\n name='dilution buffer',\n description='dilution buffer',\n display_color='#FF0000',\n )\n mastermix_liq = ctx.define_liquid(\n name='mastermix',\n description='mastermix',\n display_color='#FBFF00',\n )\n sample_liq = ctx.define_liquid(\n name='sample',\n description='sample, NTC, and DAC',\n display_color='#F300FF',\n )\n pc_liq = ctx.define_liquid(\n name='positive control',\n description='diluted 1:100',\n display_color='#050F5D',\n )\n\n # load liquids\n [s.load_liquid(sample_liq, volume=200/num_samples) for s in samples]\n pc.load_liquid(pc_liq, volume=200)\n if not type_molecule == 'pDNA':\n rxn_mix_1.load_liquid(rxn_mix_1_liq, volume=30*num_cols*8*1.1+2000)\n if not type_molecule == '101':\n rxn_mix_2.load_liquid(\n rxn_mix_2_liq, volume=vol_rxn_mix_2*num_cols*8*1.1+2000)\n mm.load_liquid(mastermix_liq, volume=16.5*len(data)*4*1.1+2000)\n [d.load_liquid(diluent_liq, volume=1200)\n for d in diluent[:math.ceil(num_cols*4/3)]]\n\n except: # noqa\n pass\n\n def pick_up(pip):\n try:\n pip.pick_up_tip()\n except protocol_api.labware.OutOfTipsError:\n ctx.pause('Replace the tips')\n pip.reset_tipracks()\n pip.pick_up_tip()\n\n vol_max_dil = 0.8*diluent[0].max_volume\n vol_current = 0\n dil_tracker = iter(diluent)\n dil_current = next(dil_tracker)\n\n def track_dilution(vol):\n nonlocal vol_current\n nonlocal dil_current\n vol_actual = vol*8 # multi-channel pipette\n if vol_actual + vol_current > vol_max_dil:\n vol_current = 0\n dil_current = next(dil_tracker)\n vol_current += vol_actual\n return dil_current\n\n def wick(pip, well, side=1):\n if well.diameter:\n radius = well.diameter/2\n else:\n radius = well.width/2\n pip.move_to(well.bottom().move(Point(x=side*radius*0.7, z=3)))\n\n def slow_withdraw(pip, well, delay=2.0):\n pip.default_speed /= 16\n ctx.delay(seconds=delay)\n pip.move_to(well.top())\n pip.default_speed *= 16\n\n rxn_mix_1_dests = [tc_plate.rows()[0][i*4+1] for i in range(num_cols)]\n if not type_molecule == 'pDNA':\n # first dilution\n first_dil_dests_m = [tc_plate.rows()[0][i*4] for i in range(num_cols)]\n pick_up(m300)\n vol_dil = 180\n for d in first_dil_dests_m:\n source = track_dilution(vol_dil)\n m300.aspirate(vol_dil, source)\n slow_withdraw(m300, source)\n m300.dispense(vol_dil, d.bottom(5))\n slow_withdraw(m300, d)\n m300.drop_tip()\n\n pick_up(m300)\n for d in rxn_mix_1_dests:\n m300.aspirate(30, rxn_mix_1)\n slow_withdraw(m300, rxn_mix_1)\n m300.dispense(30, d.bottom(2))\n slow_withdraw(m300, d)\n m300.drop_tip()\n\n # transfer sample\n first_dil_cols = [tc_plate.columns()[i*4] for i in range(num_cols)]\n first_dil_dests_s = [\n well for col in first_dil_cols for well in col][:num_samples]\n for i, (s, d) in enumerate(zip(samples, first_dil_dests_s)):\n pick_up(p20)\n p20.aspirate(20, s.bottom(0.5))\n slow_withdraw(p20, s)\n p20.dispense(20, d.bottom(d.depth/2))\n # p20.mix(5, 20, d.bottom(d.depth/2))\n slow_withdraw(p20, d)\n if i % 8 == 0: # row A\n p20.move_to(d.top(2))\n p20.move_to(d.top().move(Point(y=-5, z=2)))\n p20.drop_tip()\n\n # add to mix\n for s, d in zip(first_dil_dests_m, rxn_mix_1_dests):\n pick_up(m300)\n m300.mix(5, 100, s.bottom(s.depth/2))\n m300.aspirate(20, s.bottom(5))\n slow_withdraw(m300, s)\n m300.dispense(20, d.bottom(2))\n m300.mix(5, 20, d.bottom(2))\n slow_withdraw(m300, d)\n m300.drop_tip()\n\n tc.close_lid()\n if DO_THERMOCYCLER:\n tc.set_lid_temperature(105)\n tc.set_block_temperature(37, hold_time_minutes=30)\n tc.open_lid()\n\n else:\n # rxn mix 2\n for d in rxn_mix_1_dests:\n\n pick_up(m300)\n m300.aspirate(vol_rxn_mix_2, rxn_mix_2)\n slow_withdraw(m300, rxn_mix_2)\n m300.dispense(vol_rxn_mix_2, d.bottom(2))\n # m300.mix(5, 20, d.bottom(d.depth/2))\n slow_withdraw(m300, d)\n m300.drop_tip()\n rxn_mix_1_columns = [\n tc_plate.columns()[tc_plate.rows()[0].index(col)]\n for col in rxn_mix_1_dests]\n rxn_mix_1_s = [\n well for col in rxn_mix_1_columns for well in col][:num_samples]\n for s, d in zip(samples, rxn_mix_1_s):\n pick_up(p20)\n p20.aspirate(10, s.bottom(0.5))\n slow_withdraw(p20, s)\n p20.dispense(10, d.top(-5))\n p20.mix(5, 20, d.bottom(d.depth/2))\n slow_withdraw(p20, d)\n p20.drop_tip()\n\n if not type_molecule == '101':\n if type_molecule == '401': # rxn mix 2\n for d in rxn_mix_1_dests:\n pick_up(m300)\n m300.aspirate(50, rxn_mix_2)\n slow_withdraw(m300, rxn_mix_2)\n m300.dispense(50, d.bottom(2))\n m300.mix(5, 20, d.bottom(2), rate=0.5)\n slow_withdraw(m300, d)\n m300.drop_tip()\n\n tc.close_lid()\n if DO_THERMOCYCLER:\n tc.set_block_temperature(55, hold_time_minutes=30)\n tc.set_block_temperature(95, hold_time_minutes=15)\n tc.set_block_temperature(4)\n tc.open_lid()\n tc.deactivate_lid()\n\n dil_sets_tc = [\n tc_plate.rows()[0][i*4+2:i*4+4] for i in range(num_cols)\n ]\n dil_sets_dil = [\n dil_plate.rows()[0][i*4:i*4+4] for i in range(num_cols)\n ]\n dil_sets_all = []\n for set_t, set_d in zip(dil_sets_tc, dil_sets_dil):\n dil_set = set_t + set_d\n dil_sets_all.append(dil_set)\n\n # add diluent to all\n pick_up(m300)\n vol_dil = 180\n for d_set in dil_sets_all:\n for d in d_set:\n source = track_dilution(vol_dil)\n m300.aspirate(vol_dil, source)\n slow_withdraw(m300, source)\n m300.dispense(vol_dil, d.bottom(5))\n slow_withdraw(m300, d)\n\n def mix_high_low(reps, vol, well, h_low, h_high):\n for _ in range(reps):\n m300.aspirate(vol, well.bottom(h_low))\n m300.dispense(vol, well.bottom(h_high))\n\n # perform dilutions\n for i, dil_set in enumerate(dil_sets_all):\n sources = [rxn_mix_1_dests[i]] + dil_set[:len(dil_sets_all[0])-1]\n dests = dil_set\n for s, d in zip(sources, dests):\n if not m300.has_tip:\n pick_up(m300)\n m300.mix(1, 20, s.bottom(5))\n m300.aspirate(20, s.bottom(5))\n slow_withdraw(m300, s)\n m300.dispense(20, d.bottom(d.depth/2))\n mix_high_low(8, 50, d, d.depth/2-2, d.depth/2+3)\n m300.mix(8, 50, d.bottom(d.depth/2))\n slow_withdraw(m300, d)\n m300.drop_tip()\n\n # mm\n mm_dest_sets = [\n mm_plate.rows()[i % 8][(i//8)*4:(i//8 + 1)*4]\n for i in range(len(data)+1)]\n pick_up(p20)\n for d_set in mm_dest_sets:\n for d in d_set:\n p20.aspirate(2, mm.top()) # pre-airgap\n p20.aspirate(16.5, mm)\n slow_withdraw(p20, mm)\n p20.dispense(p20.current_volume, d.bottom(1))\n slow_withdraw(p20, d)\n p20.drop_tip()\n\n # add diluted positive control\n pc_mm_dest_set = mm_dest_sets.pop(2)\n pick_up(p20)\n for d in pc_mm_dest_set:\n if not p20.has_tip:\n pick_up(p20)\n p20.aspirate(2, pc.bottom(0.5)) # pre-airgap\n p20.aspirate(5.5, pc.bottom(0.5))\n slow_withdraw(p20, pc)\n p20.dispense(5.5, d.bottom(2))\n slow_withdraw(p20, d)\n p20.drop_tip()\n\n # cherrypick\n cp_lw_map = {\n 'T': tc_plate,\n 'D': dil_plate\n }\n cp_sources = [\n cp_lw_map[line[1][0]].wells_by_name()[line[0]]\n for line in data]\n for s, d_set in zip(cp_sources, mm_dest_sets):\n for d in d_set:\n pick_up(p20)\n p20.aspirate(2, s.bottom(5)) # pre-airgap\n p20.aspirate(5.5, s.bottom(5))\n slow_withdraw(p20, s)\n p20.dispense(5.5, d.bottom(2))\n slow_withdraw(p20, d)\n p20.drop_tip()\n\n # fill remaining columns if necessary\n num_mm_dest_sets = len(data) + 1 # including PC\n if num_mm_dest_sets % 8 == 0:\n remaining_rows = 0\n else:\n remaining_rows = 8 - num_mm_dest_sets % 8\n mm_dest_sets_blank = [\n mm_plate.rows()[i % 8][(i//8)*4:(i//8 + 1)*4]\n for i in range(num_mm_dest_sets, num_mm_dest_sets+remaining_rows)]\n vol_blank = 22.0\n tip_ref_vol = p20.tip_racks[0].wells()[0].max_volume - 2.0 # vol preairgap\n num_trans = math.ceil(vol_blank/tip_ref_vol)\n vol_per_trans = round(vol_blank/num_trans, 2)\n pick_up(p20)\n for dest_set in mm_dest_sets_blank:\n for d in dest_set:\n for _ in range(num_trans):\n source = track_dilution(vol_per_trans)\n p20.aspirate(2, source.top()) # pre-airgap\n p20.aspirate(vol_per_trans, source)\n slow_withdraw(p20, source)\n p20.dispense(p20.current_volume, d.bottom(2))\n slow_withdraw(p20, d)\n p20.drop_tip()\n\n tc.deactivate_block()\n", "custom_labware_defs": [ { "brand": { diff --git a/protocols/052d03/tc.ot2.apiv2.py b/protocols/052d03/tc.ot2.apiv2.py index b5af31fdf..026ccda63 100644 --- a/protocols/052d03/tc.ot2.apiv2.py +++ b/protocols/052d03/tc.ot2.apiv2.py @@ -267,6 +267,11 @@ def slow_withdraw(pip, well, delay=2.0): m300.dispense(vol_dil, d.bottom(5)) slow_withdraw(m300, d) + def mix_high_low(reps, vol, well, h_low, h_high): + for _ in range(reps): + m300.aspirate(vol, well.bottom(h_low)) + m300.dispense(vol, well.bottom(h_high)) + # perform dilutions for i, dil_set in enumerate(dil_sets_all): sources = [rxn_mix_1_dests[i]] + dil_set[:len(dil_sets_all[0])-1] @@ -274,10 +279,12 @@ def slow_withdraw(pip, well, delay=2.0): for s, d in zip(sources, dests): if not m300.has_tip: pick_up(m300) + m300.mix(1, 20, s.bottom(5)) m300.aspirate(20, s.bottom(5)) slow_withdraw(m300, s) m300.dispense(20, d.bottom(d.depth/2)) - m300.mix(5, 50, d.bottom(d.depth/2)) + mix_high_low(8, 50, d, d.depth/2-2, d.depth/2+3) + m300.mix(8, 50, d.bottom(d.depth/2)) slow_withdraw(m300, d) m300.drop_tip() @@ -301,10 +308,10 @@ def slow_withdraw(pip, well, delay=2.0): for d in pc_mm_dest_set: if not p20.has_tip: pick_up(p20) - p20.aspirate(2, pc.top()) # pre-airgap + p20.aspirate(2, pc.bottom(0.5)) # pre-airgap p20.aspirate(5.5, pc.bottom(0.5)) slow_withdraw(p20, pc) - p20.dispense(p20.current_volume, d.bottom(2)) + p20.dispense(5.5, d.bottom(2)) slow_withdraw(p20, d) p20.drop_tip() @@ -319,10 +326,10 @@ def slow_withdraw(pip, well, delay=2.0): for s, d_set in zip(cp_sources, mm_dest_sets): for d in d_set: pick_up(p20) - p20.aspirate(2, s.top()) # pre-airgap + p20.aspirate(2, s.bottom(5)) # pre-airgap p20.aspirate(5.5, s.bottom(5)) slow_withdraw(p20, s) - p20.dispense(p20.current_volume, d.bottom(2)) + p20.dispense(5.5, d.bottom(2)) slow_withdraw(p20, d) p20.drop_tip()