Skip to content

Commit

Permalink
Merge pull request #5061 from Opentrons/6d901d-fix
Browse files Browse the repository at this point in the history
fix(protocols/6d901): pick up less than 8 with multi-channel for 7.2+
  • Loading branch information
ramifarawi authored Mar 19, 2024
2 parents 74fc154 + 2ff92ba commit a87dfd5
Show file tree
Hide file tree
Showing 5 changed files with 20 additions and 21 deletions.
15 changes: 7 additions & 8 deletions data/data/fields.csv
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ init_vol,3
init_vol_50,1
init_vol_bca,1
init_vol_bsa,1
init_vol_buff,2
init_vol_buff,1
init_vol_buff1,1
init_vol_buff2,1
init_vol_buff3,1
Expand All @@ -586,7 +586,7 @@ init_vol_standard,1
init_vols_csv,1
initial_denaturation_cycles,1
initial_vol,1
input_csv,23
input_csv,22
input_file,10
input_file2,6
input_labware,1
Expand Down Expand Up @@ -643,7 +643,6 @@ labware_collect_plate,1
labware_cultureplate,1
labware_deep_well,1
labware_dest,2
labware_dna_plate,1
labware_dna_sample_plate,1
labware_elisa_plate,3
labware_firstrna,1
Expand All @@ -655,7 +654,7 @@ labware_p300_tips,1
labware_parent,2
labware_patient_samples,1
labware_pcr,1
labware_pcr_plate,11
labware_pcr_plate,10
labware_plate,1
labware_plates,9
labware_pool,1
Expand Down Expand Up @@ -991,7 +990,7 @@ p1kmnt,1
p1n,1
p1num,1
p20_blowout_height,1
p20_mount,137
p20_mount,136
p20_multi_mount,3
p20_rate,2
p20_reservoir_height,1
Expand All @@ -1008,7 +1007,7 @@ p2num,1
p300_gen,1
p300_mixing_height,1
p300_mnt,3
p300_mount,160
p300_mount,159
p300_mount_1,1
p300_multi_mount,7
p300_rate,1
Expand Down Expand Up @@ -1450,7 +1449,7 @@ te_well,2
temp,2
temp_gen,1
temp_lysate,1
temp_mod,3
temp_mod,2
temp_mod_lname,2
temp_mod_on,2
temp_mod_s1_lname,1
Expand All @@ -1471,7 +1470,7 @@ tempblock,1
tempdeck_gen,1
tempdeck_name,1
tempdeck_slot,1
temperature,13
temperature,12
temperature1,1
temperature2,1
tempgen,1
Expand Down
2 changes: 1 addition & 1 deletion protoBuilds/6d901d-2/6d901d-2.ot2.apiv2.py.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"content": "from opentrons import protocol_api\nfrom opentrons.protocol_api.labware import OutOfTipsError\nfrom opentrons.types import Mount\n\n\nmetadata = {\n 'protocolName':\n ('Cherrypicking with multi-channel pipette substituting for a single '\n 'channel pipette'),\n 'author': 'Nick & Eskil <[email protected]>',\n 'source': 'Custom Protocol Request',\n 'apiLevel': '2.12'\n}\n\n\ndef run(ctx: protocol_api.ProtocolContext):\n\n [transfer_csv,\n lw_source_plate,\n lw_source_plate_open,\n lw_dest_plate,\n lw_dest_plate_open,\n res_type,\n pipette_type,\n pipette_mount,\n tip_type,\n tip_reuse,\n starting_tiprack_slot,\n starting_tip_well] = get_values( # noqa: F821\n \"transfer_csv\",\n \"lw_source_plate\",\n \"lw_source_plate_open\",\n \"lw_dest_plate\",\n \"lw_dest_plate_open\",\n \"res_type\",\n \"pipette_type\",\n \"pipette_mount\",\n \"tip_type\",\n \"tip_reuse\",\n \"starting_tiprack_slot\",\n \"starting_tip_well\")\n\n tiprack_map = {\n 'p20_multi_gen2': {\n 'standard': 'opentrons_96_tiprack_20ul',\n 'filter': 'opentrons_96_filtertiprack_20ul'\n },\n 'p300_multi_gen2': {\n 'standard': 'opentrons_96_tiprack_300ul',\n 'filter': 'opentrons_96_filtertiprack_200ul'\n }\n }\n\n # Parse csv\n # Format: Source Well, Source Aspiration Height Above Bottom (in mm),\n # Dest Well, Vol (in ul)\n transfer_info = [[val.strip().lower() for val in line.split(',')]\n for line in transfer_csv.splitlines()\n if line.split(',')[0].strip()][1:]\n\n if lw_source_plate_open.strip():\n lw_source_plate_name = lw_source_plate_open\n else:\n lw_source_plate_name = lw_source_plate\n if lw_dest_plate_open.strip():\n lw_dest_plate_name = lw_dest_plate_open\n else:\n lw_dest_plate_name = lw_dest_plate\n\n # Load labware\n # Plate to cherrypick from\n source_plate = ctx.load_labware(lw_source_plate_name, '7')\n dest_plate = ctx.load_labware(lw_dest_plate_name, '8')\n # This reservoir is unused, but present\n if res_type != \"none\":\n ctx.load_labware(res_type, '9')\n\n # Load tipracks\n tip_name = tiprack_map[pipette_type][tip_type]\n tiprack_slots = ['4', '5', '10', '11']\n tipracks = [ctx.load_labware(tip_name, slot)\n for slot in tiprack_slots]\n\n # load pipette\n pip = ctx.load_instrument(pipette_type, pipette_mount, tip_racks=tipracks)\n\n if not ctx.is_simulating():\n pick_up_current = 0.1 # 100 mA for single tip\n # Uncomment the next two lines if using Opentrons Robot Software version 7.1.x. # noqa: E501\n # Comment them if NOT using 7.1.x\n\n ctx._hw_manager.hardware.get_pipette(Mount.string_to_mount(pip.mount)).update_config_item( # noqa: E501\n {'pick_up_current': {8: pick_up_current}})\n\n # Uncomment the next two lines if using Opentrons Robot Software version 7.2.x # noqa: E501\n # Comment them if NOT using 7.2.x\n\n # ctx._hw_manager.hardware.get_pipette(Mount.string_to_mount(pip.mount)).update_config_item(\n # {'pick_up_current': pick_up_current})\n\n # Tip_map has the columns reversed, pipette always picks up the\n # bottom-most tip in a given column until the column is depleted, and then\n # moves to the next column (from left to right).\n tip_map = []\n for rack in tipracks:\n tip_map.append(\n [[col for col in reversed(column)] for column in rack.columns()])\n # Flag at the end of each rack that is true if there are tips left\n for rack in tip_map:\n rack.append(True)\n # Flag used tipracks based on the protocol input parameter.\n # Check that the input parameter is an existing tiprack slot\n if starting_tiprack_slot not in tiprack_slots:\n raise Exception(\n f\"The Starting Tiprack Slot ({starting_tiprack_slot}) is invalid \"\n f\"The valid tiprack slots are {tiprack_slots}\"\n )\n start_rack_index = tiprack_slots.index(starting_tiprack_slot)\n for i in range(start_rack_index):\n tip_map[i][-1] = False\n\n # Flag used tips in the first available tiprack\n for column in tip_map[start_rack_index]:\n is_break = False\n for well in column:\n if well.well_name != starting_tip_well:\n well.has_tip = False\n else:\n is_break = True\n break\n if is_break:\n break\n\n def pick_up(pipette):\n \"\"\"`pick_up()` will pause the ctx when all tip boxes are out of\n tips, prompting the user to replace all tip racks. Once tipracks are\n reset, the ctx will start picking up tips from the first tip\n box as defined in the slot order when assigning the labware definition\n for that tip box. `pick_up()` will track tips for both pipettes if\n applicable.\n\n :param pipette: The pipette desired to pick up tip\n as definited earlier in the ctx (e.g. p300, m20).\n \"\"\"\n for i, rack in enumerate(tip_map):\n # Check the flag to see if the rack is empty, then we don't loop\n # through that rack so that the algorithm executes faster.\n if rack[-1] is False:\n if i == len(tip_map) - 1: # All tips are used, time to reset\n ctx.pause(\"Replace empty tip racks\")\n # print(\"Replace empty tip racks\")\n pipette.reset_tipracks()\n for rack in tip_map:\n rack[-1] = True\n # Raise an exception so that we can retry the pick up\n raise OutOfTipsError(\n \"Tipracks were out of tips and were reset\")\n else:\n continue\n for column in rack[:-1]: # skip [-1] index because it's the flag\n for well in column:\n if well.has_tip:\n pipette.pick_up_tip(well)\n if well.well_name == 'A12': # last tip in the rack\n rack[-1] = False\n return\n\n def parse_well(well):\n letter = well[0]\n number = well[1:]\n return letter.upper() + str(int(number))\n\n # import pdb; pdb.set_trace()\n if tip_reuse == 'always':\n try:\n pick_up(pip)\n except OutOfTipsError:\n # Try again after tipracks are reset\n pick_up(pip)\n for line in transfer_info:\n s_well, h, d_well, vol = line[:4]\n source_locn = \\\n source_plate.wells_by_name()[parse_well(s_well)].bottom(float(h))\n dest_locn = \\\n dest_plate.wells_by_name()[parse_well(d_well)]\n if tip_reuse == 'never':\n try:\n pick_up(pip)\n except OutOfTipsError:\n # Try again after tipracks are reset\n pick_up(pip)\n # pip.transfer(float(vol), source_locn, dest_locn, new_tip='never')\n pip.aspirate(float(vol), source_locn)\n pip.dispense(float(vol), dest_locn)\n if tip_reuse == 'never':\n pip.drop_tip()\n if pip.has_tip:\n pip.drop_tip()\n",
"content": "from opentrons import protocol_api\nfrom opentrons.protocol_api.labware import OutOfTipsError\nfrom opentrons.types import Mount\n\n\nmetadata = {\n 'protocolName':\n ('Cherrypicking with multi-channel pipette substituting for a single '\n 'channel pipette'),\n 'author': 'Nick & Eskil <[email protected]>',\n 'source': 'Custom Protocol Request',\n 'apiLevel': '2.12'\n}\n\n\ndef run(ctx: protocol_api.ProtocolContext):\n\n [transfer_csv,\n lw_source_plate,\n lw_source_plate_open,\n lw_dest_plate,\n lw_dest_plate_open,\n res_type,\n pipette_type,\n pipette_mount,\n tip_type,\n tip_reuse,\n starting_tiprack_slot,\n starting_tip_well] = get_values( # noqa: F821\n \"transfer_csv\",\n \"lw_source_plate\",\n \"lw_source_plate_open\",\n \"lw_dest_plate\",\n \"lw_dest_plate_open\",\n \"res_type\",\n \"pipette_type\",\n \"pipette_mount\",\n \"tip_type\",\n \"tip_reuse\",\n \"starting_tiprack_slot\",\n \"starting_tip_well\")\n\n tiprack_map = {\n 'p20_multi_gen2': {\n 'standard': 'opentrons_96_tiprack_20ul',\n 'filter': 'opentrons_96_filtertiprack_20ul'\n },\n 'p300_multi_gen2': {\n 'standard': 'opentrons_96_tiprack_300ul',\n 'filter': 'opentrons_96_filtertiprack_200ul'\n }\n }\n\n # Parse csv\n # Format: Source Well, Source Aspiration Height Above Bottom (in mm),\n # Dest Well, Vol (in ul)\n transfer_info = [[val.strip().lower() for val in line.split(',')]\n for line in transfer_csv.splitlines()\n if line.split(',')[0].strip()][1:]\n\n if lw_source_plate_open.strip():\n lw_source_plate_name = lw_source_plate_open\n else:\n lw_source_plate_name = lw_source_plate\n if lw_dest_plate_open.strip():\n lw_dest_plate_name = lw_dest_plate_open\n else:\n lw_dest_plate_name = lw_dest_plate\n\n # Load labware\n # Plate to cherrypick from\n source_plate = ctx.load_labware(lw_source_plate_name, '7')\n dest_plate = ctx.load_labware(lw_dest_plate_name, '8')\n # This reservoir is unused, but present\n if res_type != \"none\":\n ctx.load_labware(res_type, '9')\n\n # Load tipracks\n tip_name = tiprack_map[pipette_type][tip_type]\n tiprack_slots = ['4', '5', '10', '11']\n tipracks = [ctx.load_labware(tip_name, slot)\n for slot in tiprack_slots]\n\n # load pipette\n pip = ctx.load_instrument(pipette_type, pipette_mount, tip_racks=tipracks)\n\n if not ctx.is_simulating():\n pick_up_current = 0.1 # 100 mA for single tip\n # Uncomment the next two lines if using Opentrons Robot Software version 7.1.x. # noqa: E501\n # Comment them if NOT using 7.1.x\n\n # ctx._hw_manager.hardware.get_pipette(Mount.string_to_mount(pip.mount)).update_config_item( # noqa: E501\n # {'pick_up_current': {8: pick_up_current}})\n\n # Uncomment the next two lines if using Opentrons Robot Software version 7.2.x # noqa: E501\n # Comment them if NOT using 7.2.x\n\n ctx._hw_manager.hardware.get_pipette(Mount.string_to_mount(pip.mount)).update_config_item( # noqa: E501\n {'pick_up_current': pick_up_current})\n\n # Tip_map has the columns reversed, pipette always picks up the\n # bottom-most tip in a given column until the column is depleted, and then\n # moves to the next column (from left to right).\n tip_map = []\n for rack in tipracks:\n tip_map.append(\n [[col for col in reversed(column)] for column in rack.columns()])\n # Flag at the end of each rack that is true if there are tips left\n for rack in tip_map:\n rack.append(True)\n # Flag used tipracks based on the protocol input parameter.\n # Check that the input parameter is an existing tiprack slot\n if starting_tiprack_slot not in tiprack_slots:\n raise Exception(\n f\"The Starting Tiprack Slot ({starting_tiprack_slot}) is invalid \"\n f\"The valid tiprack slots are {tiprack_slots}\"\n )\n start_rack_index = tiprack_slots.index(starting_tiprack_slot)\n for i in range(start_rack_index):\n tip_map[i][-1] = False\n\n # Flag used tips in the first available tiprack\n for column in tip_map[start_rack_index]:\n is_break = False\n for well in column:\n if well.well_name != starting_tip_well:\n well.has_tip = False\n else:\n is_break = True\n break\n if is_break:\n break\n\n def pick_up(pipette):\n \"\"\"`pick_up()` will pause the ctx when all tip boxes are out of\n tips, prompting the user to replace all tip racks. Once tipracks are\n reset, the ctx will start picking up tips from the first tip\n box as defined in the slot order when assigning the labware definition\n for that tip box. `pick_up()` will track tips for both pipettes if\n applicable.\n\n :param pipette: The pipette desired to pick up tip\n as definited earlier in the ctx (e.g. p300, m20).\n \"\"\"\n for i, rack in enumerate(tip_map):\n # Check the flag to see if the rack is empty, then we don't loop\n # through that rack so that the algorithm executes faster.\n if rack[-1] is False:\n if i == len(tip_map) - 1: # All tips are used, time to reset\n ctx.pause(\"Replace empty tip racks\")\n # print(\"Replace empty tip racks\")\n pipette.reset_tipracks()\n for rack in tip_map:\n rack[-1] = True\n # Raise an exception so that we can retry the pick up\n raise OutOfTipsError(\n \"Tipracks were out of tips and were reset\")\n else:\n continue\n for column in rack[:-1]: # skip [-1] index because it's the flag\n for well in column:\n if well.has_tip:\n pipette.pick_up_tip(well)\n if well.well_name == 'A12': # last tip in the rack\n rack[-1] = False\n return\n\n def parse_well(well):\n letter = well[0]\n number = well[1:]\n return letter.upper() + str(int(number))\n\n # import pdb; pdb.set_trace()\n if tip_reuse == 'always':\n try:\n pick_up(pip)\n except OutOfTipsError:\n # Try again after tipracks are reset\n pick_up(pip)\n for line in transfer_info:\n s_well, h, d_well, vol = line[:4]\n source_locn = \\\n source_plate.wells_by_name()[parse_well(s_well)].bottom(float(h))\n dest_locn = \\\n dest_plate.wells_by_name()[parse_well(d_well)]\n if tip_reuse == 'never':\n try:\n pick_up(pip)\n except OutOfTipsError:\n # Try again after tipracks are reset\n pick_up(pip)\n # pip.transfer(float(vol), source_locn, dest_locn, new_tip='never')\n pip.aspirate(float(vol), source_locn)\n pip.dispense(float(vol), dest_locn)\n if tip_reuse == 'never':\n pip.drop_tip()\n if pip.has_tip:\n pip.drop_tip()\n",
"custom_labware_defs": [
{
"brand": {
Expand Down
Loading

0 comments on commit a87dfd5

Please sign in to comment.