From 97302071a6efe3b74da5d0bcaff93552905f4170 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Cramifarawi=E2=80=9D?= <“rami.farawi@opentrons.com”> Date: Wed, 21 Feb 2024 13:44:51 -0500 Subject: [PATCH] fix --- protoBuilds/6d901d-2/6d901d-2.ot2.apiv2.py.json | 2 +- protoBuilds/6d901d-2/README.json | 4 ++-- protoBuilds/6d901d/6d901d.ot2.apiv2.py.json | 2 +- protoBuilds/6d901d/README.json | 4 ++-- protocols/6d901d-2/6d901d-2.ot2.apiv2.py | 2 +- protocols/6d901d-2/README.md | 2 +- protocols/6d901d/6d901d.ot2.apiv2.py | 2 +- protocols/6d901d/README.md | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/protoBuilds/6d901d-2/6d901d-2.ot2.apiv2.py.json b/protoBuilds/6d901d-2/6d901d-2.ot2.apiv2.py.json index 85a51d251..fd3b265be 100644 --- a/protoBuilds/6d901d-2/6d901d-2.ot2.apiv2.py.json +++ b/protoBuilds/6d901d-2/6d901d-2.ot2.apiv2.py.json @@ -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 ',\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, Volume (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 ',\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", "custom_labware_defs": [ { "brand": { diff --git a/protoBuilds/6d901d-2/README.json b/protoBuilds/6d901d-2/README.json index 303575ce4..4f005a893 100644 --- a/protoBuilds/6d901d-2/README.json +++ b/protoBuilds/6d901d-2/README.json @@ -8,14 +8,14 @@ "deck-setup": "\nExample deck setup.\n\n\n", "description": "A protocol based on our most robust cherrypicking protocol that has been modified to use a multi-channel pipette as single channel by only picking up a single tip at a time. Specify aspiration height, pipette, as well as source and destination wells with this all inclusive cherrypicking protocol.\nThis is an optional Part 2 protocol to its corresponding Part 1: Normalization protocol using a multi-channel pipette\nNote: This protocol was updated for a change in our software stack and will require app 7.0 or greater.\n\nExplanation of complex parameters below:\n\ninput .csv file: Here, you should upload a .csv file formatted in the following way, making sure to include headers in your csv file.\nSource Plate Type: The plate that you want to cherrypick samples from.\nDestination Plate Type: The plate that you want to dispense cherrypicked samples in.\nReservoir Type: A placeholder from part 1 of this protocol, it should be the same as the reservoir from part 1, although it is not used in this protocol. If there is no reservoir present in slot 9 you can set it to None.\nPipette Model: Select which pipette you will use for this protocol.\nPipette Mount: Specify which mount your multi-channel pipette is on (left or right)\nTip Type: Specify whether you want to use filter- or regular tips.\nTip Usage Strategy: Specify whether you'd like to use a new tip for each transfer, or keep the same tip throughout the protocol.\nStarting Tiprack Slot: If you want to start this protocol right after finishing part 1 without replacing your tipracks you can designate the first non-empty tiprack on the deck to start picking up tips from, otherwise leave this parameter at its default value of slot 4. The tipracks are ordered from first to last as slot 4, 5, 10, and 11.\nStarting Tip Well: Indicate the first well of the first non-empty tiprack containing a tip, e.g. H5, or B3, etc. Leave this parameter with the default value of H1 if starting with fresh tipracks.\n\n", "internal": "6d901d-2", - "labware": "\nAny verified labware found in our Labware Library and some additional microplates (see plate options for source and destination plates parameters below, e.g. Greiner Bio-One plates)\n", + "labware": "\nAny verified labware found in our Labware Library and some additional microplates (see plate options for source and destination plates parameters below, e.g. Greiner Bio-One plates).\n", "markdown": { "author": "[Opentrons](https://opentrons.com/)\n\n", "categories": "* Sample Prep\n\t* Cherrypicking\n\n", "deck-setup": "* Example deck setup.\n![deck layout](https://opentrons-protocol-library-website.s3.amazonaws.com/custom-README-images/6d901d/2/example_deck.jpg)\n\n---\n\n", "description": "\nA protocol based on our most robust [cherrypicking protocol](https://protocols.opentrons.com/protocol/cherrypicking) that has been modified to use a multi-channel pipette as single channel by only picking up a single tip at a time. Specify aspiration height, pipette, as well as source and destination wells with this all inclusive cherrypicking protocol.\n\nThis is an optional Part 2 protocol to its corresponding [Part 1: Normalization protocol using a multi-channel pipette](https://protocols.opentrons.com/protocol/6d901d)\n\n**Note**: This protocol was updated for a change in our software stack and will require app 7.0 or greater.\n\n![Cherrypicking Example](https://opentrons-protocol-library-website.s3.amazonaws.com/custom-README-images/cherrypicking/cherrypicking_example.png)\n\nExplanation of complex parameters below:\n\n* `input .csv file`: Here, you should upload a .csv file formatted in the [following way](https://opentrons-protocol-library-website.s3.amazonaws.com/custom-README-images/6d901d/2/example.csv), making sure to include headers in your csv file.\n* `Source Plate Type`: The plate that you want to cherrypick samples from.\n* `Destination Plate Type`: The plate that you want to dispense cherrypicked samples in.\n* `Reservoir Type`: A placeholder from part 1 of this protocol, it should be the same as the reservoir from part 1, although it is not used in this protocol. If there is no reservoir present in slot 9 you can set it to None.\n* `Pipette Model`: Select which pipette you will use for this protocol.\n* `Pipette Mount`: Specify which mount your multi-channel pipette is on (left or right)\n* `Tip Type`: Specify whether you want to use filter- or regular tips.\n* `Tip Usage Strategy`: Specify whether you'd like to use a new tip for each transfer, or keep the same tip throughout the protocol.\n* `Starting Tiprack Slot`: If you want to start this protocol right after finishing part 1 without replacing your tipracks you can designate the first non-empty tiprack on the deck to start picking up tips from, otherwise leave this parameter at its default value of slot 4. The tipracks are ordered from first to last as slot 4, 5, 10, and 11.\n* `Starting Tip Well`: Indicate the first well of the first non-empty tiprack containing a tip, e.g. H5, or B3, etc. Leave this parameter with the default value of H1 if starting with fresh tipracks.\n\n---\n\n", "internal": "6d901d-2\n", - "labware": "* Any verified labware found in our [Labware Library](https://labware.opentrons.com/?category=wellPlate) and some additional microplates (see plate options for source and destination plates parameters below, e.g. Greiner Bio-One plates)\n\n", + "labware": "* Any verified labware found in our [Labware Library](https://labware.opentrons.com/?category=wellPlate) and some additional microplates (see plate options for source and destination plates parameters below, e.g. Greiner Bio-One plates).\n\n", "notes": "If you have any questions about this protocol, please contact the Protocol Development Team by filling out the [Troubleshooting Survey](https://protocol-troubleshooting.paperform.co/).\n\n", "partner": "[AstraZeneca](https://www.astrazeneca.com/)\n\n\n\n", "pipettes": "* [P20 Multi GEN2 Pipette](https://shop.opentrons.com/8-channel-electronic-pipette/)\n* [P300 Multi GEN2 Pipette](https://shop.opentrons.com/8-channel-electronic-pipette/)\n\n---\n\n", diff --git a/protoBuilds/6d901d/6d901d.ot2.apiv2.py.json b/protoBuilds/6d901d/6d901d.ot2.apiv2.py.json index c845d2595..e67fb0c9d 100644 --- a/protoBuilds/6d901d/6d901d.ot2.apiv2.py.json +++ b/protoBuilds/6d901d/6d901d.ot2.apiv2.py.json @@ -1,5 +1,5 @@ { - "content": "from opentrons import protocol_api\nfrom opentrons.types import Mount\n\nmetadata = {\n 'protocolName': 'Normalization with a multi-channel pipette \\\n used as a single-channel pipette',\n 'author': 'Opentrons ',\n 'source': 'Protocol Library',\n 'apiLevel': '2.12'\n }\n\n\ndef transpose_matrix(m):\n return [[r[i] for r in reversed(m)] for i in range(len(m[0]))]\n\n\ndef flatten_matrix(m):\n \"\"\" Converts a matrix to a 1D array, e.g. [[1,2],[3,4]] -> [1,2,3,4]\n \"\"\"\n return [cell for row in m for cell in row]\n\n\ndef well_csv_to_list(csv_string):\n \"\"\"\n Takes a csv string and flattens it to a list, re-ordering to match\n Opentrons well order convention (A1, B1, C1, ..., A2, B2, B2, ...)\n \"\"\"\n data = [\n line.split(',')\n for line in reversed(csv_string.split('\\n')) if line.strip()\n if line\n ]\n if len(data[0]) > len(data):\n # row length > column length ==> \"landscape\", so transpose\n return flatten_matrix(transpose_matrix(data))\n # \"portrait\"\n return flatten_matrix(data)\n\n\ndef run(ctx: protocol_api.ProtocolContext):\n [volumes_csv,\n p300_mount,\n p20_mount,\n plate_type,\n res_type,\n filter_tip,\n tip_reuse] = get_values( # noqa: F821\n \"volumes_csv\",\n \"p300_mount\",\n \"p20_mount\",\n \"plate_type\",\n \"res_type\",\n \"filter_tip\",\n \"tip_reuse\")\n\n # create labware\n source_plate = ctx.load_labware(plate_type, '7')\n # There could be a destination plate in slot 8 for cherry picking\n # Load something tall so the pipette doesn't hit it\n ctx.load_labware('usascientific_96_wellplate_2.4ml_deep', '8')\n reservoir = ctx.load_labware(res_type, '9')\n source = reservoir.wells()[0]\n if filter_tip:\n tips300 = ctx.load_labware('opentrons_96_filtertiprack_200ul', '10')\n tips20 = ctx.load_labware('opentrons_96_filtertiprack_20ul', '11')\n else:\n tips300 = ctx.load_labware('opentrons_96_tiprack_300ul', '10')\n tips20 = ctx.load_labware('opentrons_96_tiprack_20ul', '11')\n\n m300 = ctx.load_instrument('p300_multi_gen2', p300_mount)\n m20 = ctx.load_instrument('p20_multi_gen2', p20_mount)\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 for pipette in [m20, m300]:\n ctx._hw_manager.hardware.get_pipette(Mount.string_to_mount(pipette.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 # for pipette in [m20, m300]:\n # ctx._hw_manager.hardware.get_pipette(Mount.string_to_mount(pipette.mount)).update_config_item(\n # {'pick_up_current': pick_up_current})\n\n tip300ctr = 95\n tip20ctr = 95\n\n def pick_up(pip):\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 nonlocal tip300ctr\n nonlocal tip20ctr\n\n if pip == m300:\n if tip300ctr < 0:\n ctx.home()\n ctx.pause('Please replace tips for P300 in slot 10.')\n tip300ctr = 95\n m300.pick_up_tip(tips300.wells()[tip300ctr])\n tip300ctr -= 1\n else:\n if tip20ctr < 0:\n ctx.home()\n ctx.pause('Please replace tips for P20 in slot 11.')\n tip20ctr = 95\n m20.pick_up_tip(tips20.wells()[tip20ctr])\n tip20ctr -= 1\n\n # create volumes list\n volumes = [float(cell) for cell in well_csv_to_list(volumes_csv)]\n\n is_warning = False\n\n for vol in volumes:\n if vol < 1:\n ctx.comment(\n 'WARNING: volume {} is below pipette\\'s minimum volume.'\n .format(vol))\n is_warning = True\n\n if is_warning:\n ctx.comment(\"\\n\")\n ctx.pause(\n \"One or more minimum volume warnings were detected \"\n \"Do you wish to continue?\\n\")\n\n for i, vol in enumerate(volumes):\n pipette = m20 if vol <= 20 else m300\n if not pipette.has_tip:\n pick_up(pipette)\n if vol != 0:\n pipette.aspirate(vol, source)\n pipette.dispense(vol, source_plate.wells()[i])\n if tip_reuse == 'never':\n pipette.drop_tip()\n", + "content": "from opentrons import protocol_api\nfrom opentrons.types import Mount\n\nmetadata = {\n 'protocolName': 'Normalization with a multi-channel pipette \\\n used as a single-channel pipette',\n 'author': 'Opentrons ',\n 'source': 'Protocol Library',\n 'apiLevel': '2.12'\n }\n\n\ndef transpose_matrix(m):\n return [[r[i] for r in reversed(m)] for i in range(len(m[0]))]\n\n\ndef flatten_matrix(m):\n \"\"\" Converts a matrix to a 1D array, e.g. [[1,2],[3,4]] -> [1,2,3,4]\n \"\"\"\n return [cell for row in m for cell in row]\n\n\ndef well_csv_to_list(csv_string):\n \"\"\"\n Takes a csv string and flattens to a list, re-ordering to match\n Opentrons well order convention (A1, B1, C1, ..., A2, B2, B2, ...)\n \"\"\"\n data = [\n line.split(',')\n for line in reversed(csv_string.split('\\n')) if line.strip()\n if line\n ]\n if len(data[0]) > len(data):\n # row length > column length ==> \"landscape\", so transpose\n return flatten_matrix(transpose_matrix(data))\n # \"portrait\"\n return flatten_matrix(data)\n\n\ndef run(ctx: protocol_api.ProtocolContext):\n [volumes_csv,\n p300_mount,\n p20_mount,\n plate_type,\n res_type,\n filter_tip,\n tip_reuse] = get_values( # noqa: F821\n \"volumes_csv\",\n \"p300_mount\",\n \"p20_mount\",\n \"plate_type\",\n \"res_type\",\n \"filter_tip\",\n \"tip_reuse\")\n\n # create labware\n source_plate = ctx.load_labware(plate_type, '7')\n # There could be a destination plate in slot 8 for cherry picking\n # Load something tall so the pipette doesn't hit it\n ctx.load_labware('usascientific_96_wellplate_2.4ml_deep', '8')\n reservoir = ctx.load_labware(res_type, '9')\n source = reservoir.wells()[0]\n if filter_tip:\n tips300 = ctx.load_labware('opentrons_96_filtertiprack_200ul', '10')\n tips20 = ctx.load_labware('opentrons_96_filtertiprack_20ul', '11')\n else:\n tips300 = ctx.load_labware('opentrons_96_tiprack_300ul', '10')\n tips20 = ctx.load_labware('opentrons_96_tiprack_20ul', '11')\n\n m300 = ctx.load_instrument('p300_multi_gen2', p300_mount)\n m20 = ctx.load_instrument('p20_multi_gen2', p20_mount)\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 for pipette in [m20, m300]:\n ctx._hw_manager.hardware.get_pipette(Mount.string_to_mount(pipette.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 # for pipette in [m20, m300]:\n # ctx._hw_manager.hardware.get_pipette(Mount.string_to_mount(pipette.mount)).update_config_item(\n # {'pick_up_current': pick_up_current})\n\n tip300ctr = 95\n tip20ctr = 95\n\n def pick_up(pip):\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 nonlocal tip300ctr\n nonlocal tip20ctr\n\n if pip == m300:\n if tip300ctr < 0:\n ctx.home()\n ctx.pause('Please replace tips for P300 in slot 10.')\n tip300ctr = 95\n m300.pick_up_tip(tips300.wells()[tip300ctr])\n tip300ctr -= 1\n else:\n if tip20ctr < 0:\n ctx.home()\n ctx.pause('Please replace tips for P20 in slot 11.')\n tip20ctr = 95\n m20.pick_up_tip(tips20.wells()[tip20ctr])\n tip20ctr -= 1\n\n # create volumes list\n volumes = [float(cell) for cell in well_csv_to_list(volumes_csv)]\n\n is_warning = False\n\n for vol in volumes:\n if vol < 1:\n ctx.comment(\n 'WARNING: volume {} is below pipette\\'s minimum volume.'\n .format(vol))\n is_warning = True\n\n if is_warning:\n ctx.comment(\"\\n\")\n ctx.pause(\n \"One or more minimum volume warnings were detected \"\n \"Do you wish to continue?\\n\")\n\n for i, vol in enumerate(volumes):\n pipette = m20 if vol <= 20 else m300\n if not pipette.has_tip:\n pick_up(pipette)\n if vol != 0:\n pipette.aspirate(vol, source)\n pipette.dispense(vol, source_plate.wells()[i])\n if tip_reuse == 'never':\n pipette.drop_tip()\n", "custom_labware_defs": [ { "brand": { diff --git a/protoBuilds/6d901d/README.json b/protoBuilds/6d901d/README.json index dad1dd38e..f24800a91 100644 --- a/protoBuilds/6d901d/README.json +++ b/protoBuilds/6d901d/README.json @@ -6,13 +6,13 @@ ] }, "deck-setup": "Example deck setup starting state, note that the cherry picking plate in slot 8 is a place-holder and is used in the optional 2nd part of the protocol. The different colors on the normalization plate wells illustrates samples with different concentrations before being normalized.\n\n* Well A1 on the reservoir on slot 9: Diluent, e.g. water or buffer.", - "description": "\nConcentration Normalization is a key component of many genomic and proteomic applications, such as NGS library preparation. With this protocol, you can easily normalize the concentrations of samples in a 96 or 384 microwell plate without worrying about missing a well or adding the wrong volume. Just upload your properly formatted CSV file (keep scrolling for an example), customize your parameters, and download your ready-to-run protocol. This protocol is a modified version of our Normalization Protocol, that instead uses a multi-channel pipette as single channel pipette by picking up one tip at a time.\nThere is an optional Part 2: Cherrypicking Protocol to this protocol which performs cherrypicking using a multi-channel pipette in the same way.\nNote: This protocol was updated for a change in our software stack and will require app 7.0 or greater.\nUsing the customization fields below, set up your protocol.\n Volumes CSV: Your input CSV specifying the normalization volumes. See the Setup section below for details.\n P300 Multi Mount: Select mount for P300 Multi-Channel Pipette\n P20 Multi Mount: Select mount for P20 Multi-Channel Pipette\n Plate Type: Select the model of microwell plate to normalize samples on.\n Reservoir Type: The type of the diluent reservoir. If you are selecting a multi-well reservoir you should place your diluent in well A1.\n Use Filter Tips?: Select whether your pipette will use regular or filter tips.\n* Tip Usage Strategy: You can select whether your pipette will reuse the same tip throughout the entire normalization procedure or change tips after every diluent transfer.\n\n\nTo purchase tips, reagents, or pipettes, please visit our online store or contact our sales team at info@opentrons.com\n\nOpentrons OT-2\nOpentrons OT-2 Run App (Version 4.4.0 or later)\nOpentrons Multi-Channel Pipette and corresponding Tips\nSamples in a compatible plate (96-well or 384-well)\nAutomation-friendly reservoir\nDiluent\n\nFor more detailed information on compatible labware, please visit our Labware Library.\n\n\nCSV Format\nYour file must be saved as a comma separated value (.csv) file type. Your CSV must contain values corresponding to volumes in microliters (\u03bcL). It should be formatted in \u201clandscape\u201d orientation, with the value corresponding to well A1 in the upper left-hand corner of the value list.\n\nIn this example, 40\u03bcL will be added to A1, 41\u03bcL will be added to well B1, etc.\nIf you would like to follow our template, you can make a copy of this spreadsheet, fill out your values, and export as CSV from there.\nNote about CSV: All values corresponding to wells in the CSV must have a value (zero (0) is a valid value and nothing will be transferred to the corresponding well(s)). Additionally, the CSV can be formatted in \"portrait\" orientation. In portrait orientation, the bottom left corner is treated as A1 and the top right corner would correspond to the furthest well from A1 (H12 in a 96-well plate).", + "description": "\nConcentration Normalization is a key component of many genomic and proteomic applications, such as NGS library preparation. With this protocol, you can easily normalize the concentrations of samples in a 96 or 384 microwell plate without worrying about missing a well or adding the wrong volume. Just upload your properly formatted CSV file (keep scrolling for an example), customize your parameters, and download your ready-to-run protocol. This protocol is a modified version of our Normalization Protocol, that instead uses a multi-channel pipette as single channel pipette by picking up one tip at a time.\nThere is an optional Part 2: Cherrypicking Protocol to this protocol which performs cherrypicking using a multi-channel pipette in the same way.\nNote: This protocol was updated for a change in our software stack and requires app 7.0 or greater.\nUsing the customization fields below, set up your protocol.\n Volumes CSV: Your input CSV specifying the normalization volumes. See the Setup section below for details.\n P300 Multi Mount: Select mount for P300 Multi-Channel Pipette\n P20 Multi Mount: Select mount for P20 Multi-Channel Pipette\n Plate Type: Select the model of microwell plate to normalize samples on.\n Reservoir Type: The type of the diluent reservoir. If you are selecting a multi-well reservoir you should place your diluent in well A1.\n Use Filter Tips?: Select whether your pipette will use regular or filter tips.\n* Tip Usage Strategy: You can select whether your pipette will reuse the same tip throughout the entire normalization procedure or change tips after every diluent transfer.\n\n\nTo purchase tips, reagents, or pipettes, please visit our online store or contact our sales team at info@opentrons.com\n\nOpentrons OT-2\nOpentrons OT-2 Run App (Version 4.4.0 or later)\nOpentrons Multi-Channel Pipette and corresponding Tips\nSamples in a compatible plate (96-well or 384-well)\nAutomation-friendly reservoir\nDiluent\n\nFor more detailed information on compatible labware, please visit our Labware Library.\n\n\nCSV Format\nYour file must be saved as a comma separated value (.csv) file type. Your CSV must contain values corresponding to volumes in microliters (\u03bcL). It should be formatted in \u201clandscape\u201d orientation, with the value corresponding to well A1 in the upper left-hand corner of the value list.\n\nIn this example, 40\u03bcL will be added to A1, 41\u03bcL will be added to well B1, etc.\nIf you would like to follow our template, you can make a copy of this spreadsheet, fill out your values, and export as CSV from there.\nNote about CSV: All values corresponding to wells in the CSV must have a value (zero (0) is a valid value and nothing will be transferred to the corresponding well(s)). Additionally, the CSV can be formatted in \"portrait\" orientation. In portrait orientation, the bottom left corner is treated as A1 and the top right corner would correspond to the furthest well from A1 (H12 in a 96-well plate).", "internal": "6d901d", "markdown": { "author": "[Opentrons](https://opentrons.com/)\n\n", "categories": "* Sample Prep\n\t* Normalization with a multi-channel pipette substituting for a single-channel pipette\n\n\n", "deck-setup": "Example deck setup starting state, note that the cherry picking plate in slot 8 is a place-holder and is used in the optional 2nd part of the protocol. The different colors on the normalization plate wells illustrates samples with different concentrations before being normalized.\n![deck layout](https://opentrons-protocol-library-website.s3.amazonaws.com/custom-README-images/6d901d/example_deck.jpg)\n* Well A1 on the reservoir on slot 9: Diluent, e.g. water or buffer.\n\n", - "description": "![Normalization Example](https://opentrons-protocol-library-website.s3.amazonaws.com/custom-README-images/normalization/normalization_example.png)\n\nConcentration Normalization is a key component of many genomic and proteomic applications, such as NGS library preparation. With this protocol, you can easily normalize the concentrations of samples in a 96 or 384 microwell plate without worrying about missing a well or adding the wrong volume. Just upload your properly formatted CSV file (keep scrolling for an example), customize your parameters, and download your ready-to-run protocol. This protocol is a modified version of our [Normalization Protocol](https://protocols.opentrons.com/protocol/normalization), that instead uses a multi-channel pipette as single channel pipette by picking up one tip at a time.\n\nThere is an optional [Part 2: Cherrypicking Protocol](https://protocols.opentrons.com/protocol/6d901d-2) to this protocol which performs cherrypicking using a multi-channel pipette in the same way.\n\n**Note**: This protocol was updated for a change in our software stack and will require app 7.0 or greater.\n\nUsing the customization fields below, set up your protocol.\n* `Volumes CSV`: Your input CSV specifying the normalization volumes. See the Setup section below for details.\n* `P300 Multi Mount`: Select mount for P300 Multi-Channel Pipette\n* `P20 Multi Mount`: Select mount for P20 Multi-Channel Pipette\n* `Plate Type`: Select the model of microwell plate to normalize samples on.\n* `Reservoir Type`: The type of the diluent reservoir. If you are selecting a multi-well reservoir you should place your diluent in well A1.\n* `Use Filter Tips?`: Select whether your pipette will use regular or filter tips.\n* `Tip Usage Strategy`: You can select whether your pipette will reuse the same tip throughout the entire normalization procedure or change tips after every diluent transfer.\n\n---\n\n![Materials Needed](https://s3.amazonaws.com/opentrons-protocol-library-website/custom-README-images/001-General+Headings/materials.png)\n\nTo purchase tips, reagents, or pipettes, please visit our [online store](https://shop.opentrons.com/) or contact our sales team at [info@opentrons.com](mailto:info@opentrons.com)\n\n* [Opentrons OT-2](https://shop.opentrons.com/collections/ot-2-robot/products/ot-2)\n* [Opentrons OT-2 Run App (Version 4.4.0 or later)](https://opentrons.com/ot-app/)\n* [Opentrons Multi-Channel Pipette](https://shop.opentrons.com/8-channel-electronic-pipette/) and corresponding [Tips](https://shop.opentrons.com/collections/opentrons-tips)\n* [Samples in a compatible plate (96-well or 384-well)](https://labware.opentrons.com/?category=wellPlate)\n* [Automation-friendly reservoir](https://labware.opentrons.com/?category=reservoir)\n* Diluent\n\nFor more detailed information on compatible labware, please visit our [Labware Library](https://labware.opentrons.com/).\n\n\n---\n\n![Setup](https://s3.amazonaws.com/opentrons-protocol-library-website/custom-README-images/001-General+Headings/Setup.png)\n\n**CSV Format**\n\nYour file must be saved as a comma separated value (.csv) file type. Your CSV must contain values corresponding to volumes in microliters (\u03bcL). It should be formatted in \u201clandscape\u201d orientation, with the value corresponding to well A1 in the upper left-hand corner of the value list.\n\n![Normalization CSV](https://opentrons-protocol-library-website.s3.amazonaws.com/custom-README-images/normalization/normalization_csv.png)\n\nIn this example, 40\u03bcL will be added to A1, 41\u03bcL will be added to well B1, etc.\n\nIf you would like to follow our template, you can make a copy of [this spreadsheet](https://opentrons-protocol-library-website.s3.amazonaws.com/Technical+Notes/normalization/Opentrons+Normalization+Template.xlsx), fill out your values, and export as CSV from there.\n\n*Note about CSV*: All values corresponding to wells in the CSV must have a value (zero (0) is a valid value and nothing will be transferred to the corresponding well(s)). Additionally, the CSV can be formatted in \"portrait\" orientation. In portrait orientation, the bottom left corner is treated as A1 and the top right corner would correspond to the furthest well from A1 (H12 in a 96-well plate).\n\n\n", + "description": "![Normalization Example](https://opentrons-protocol-library-website.s3.amazonaws.com/custom-README-images/normalization/normalization_example.png)\n\nConcentration Normalization is a key component of many genomic and proteomic applications, such as NGS library preparation. With this protocol, you can easily normalize the concentrations of samples in a 96 or 384 microwell plate without worrying about missing a well or adding the wrong volume. Just upload your properly formatted CSV file (keep scrolling for an example), customize your parameters, and download your ready-to-run protocol. This protocol is a modified version of our [Normalization Protocol](https://protocols.opentrons.com/protocol/normalization), that instead uses a multi-channel pipette as single channel pipette by picking up one tip at a time.\n\nThere is an optional [Part 2: Cherrypicking Protocol](https://protocols.opentrons.com/protocol/6d901d-2) to this protocol which performs cherrypicking using a multi-channel pipette in the same way.\n\n**Note**: This protocol was updated for a change in our software stack and requires app 7.0 or greater.\n\nUsing the customization fields below, set up your protocol.\n* `Volumes CSV`: Your input CSV specifying the normalization volumes. See the Setup section below for details.\n* `P300 Multi Mount`: Select mount for P300 Multi-Channel Pipette\n* `P20 Multi Mount`: Select mount for P20 Multi-Channel Pipette\n* `Plate Type`: Select the model of microwell plate to normalize samples on.\n* `Reservoir Type`: The type of the diluent reservoir. If you are selecting a multi-well reservoir you should place your diluent in well A1.\n* `Use Filter Tips?`: Select whether your pipette will use regular or filter tips.\n* `Tip Usage Strategy`: You can select whether your pipette will reuse the same tip throughout the entire normalization procedure or change tips after every diluent transfer.\n\n---\n\n![Materials Needed](https://s3.amazonaws.com/opentrons-protocol-library-website/custom-README-images/001-General+Headings/materials.png)\n\nTo purchase tips, reagents, or pipettes, please visit our [online store](https://shop.opentrons.com/) or contact our sales team at [info@opentrons.com](mailto:info@opentrons.com)\n\n* [Opentrons OT-2](https://shop.opentrons.com/collections/ot-2-robot/products/ot-2)\n* [Opentrons OT-2 Run App (Version 4.4.0 or later)](https://opentrons.com/ot-app/)\n* [Opentrons Multi-Channel Pipette](https://shop.opentrons.com/8-channel-electronic-pipette/) and corresponding [Tips](https://shop.opentrons.com/collections/opentrons-tips)\n* [Samples in a compatible plate (96-well or 384-well)](https://labware.opentrons.com/?category=wellPlate)\n* [Automation-friendly reservoir](https://labware.opentrons.com/?category=reservoir)\n* Diluent\n\nFor more detailed information on compatible labware, please visit our [Labware Library](https://labware.opentrons.com/).\n\n\n---\n\n![Setup](https://s3.amazonaws.com/opentrons-protocol-library-website/custom-README-images/001-General+Headings/Setup.png)\n\n**CSV Format**\n\nYour file must be saved as a comma separated value (.csv) file type. Your CSV must contain values corresponding to volumes in microliters (\u03bcL). It should be formatted in \u201clandscape\u201d orientation, with the value corresponding to well A1 in the upper left-hand corner of the value list.\n\n![Normalization CSV](https://opentrons-protocol-library-website.s3.amazonaws.com/custom-README-images/normalization/normalization_csv.png)\n\nIn this example, 40\u03bcL will be added to A1, 41\u03bcL will be added to well B1, etc.\n\nIf you would like to follow our template, you can make a copy of [this spreadsheet](https://opentrons-protocol-library-website.s3.amazonaws.com/Technical+Notes/normalization/Opentrons+Normalization+Template.xlsx), fill out your values, and export as CSV from there.\n\n*Note about CSV*: All values corresponding to wells in the CSV must have a value (zero (0) is a valid value and nothing will be transferred to the corresponding well(s)). Additionally, the CSV can be formatted in \"portrait\" orientation. In portrait orientation, the bottom left corner is treated as A1 and the top right corner would correspond to the furthest well from A1 (H12 in a 96-well plate).\n\n\n", "internal": "6d901d\n", "notes": "\nIf you\u2019d like to request a protocol supporting multiple plates or require any other changes to this script, please fill out our [Protocol Request Form](https://opentrons-protocol-dev.paperform.co/). You can also modify the Python file directly by following our [API Documentation](https://docs.opentrons.com/v2/). If you\u2019d like to chat with an applications engineer about changes, please contact us at [protocols@opentrons.com](mailto:protocols@opentrons.com).\n\n", "partner": "[AstraZeneca](https://www.astrazeneca.com/)\n\n\n\n", diff --git a/protocols/6d901d-2/6d901d-2.ot2.apiv2.py b/protocols/6d901d-2/6d901d-2.ot2.apiv2.py index 7d42eeae1..6833d86ca 100644 --- a/protocols/6d901d-2/6d901d-2.ot2.apiv2.py +++ b/protocols/6d901d-2/6d901d-2.ot2.apiv2.py @@ -53,7 +53,7 @@ def run(ctx: protocol_api.ProtocolContext): # Parse csv # Format: Source Well, Source Aspiration Height Above Bottom (in mm), - # Dest Well, Volume (in ul) + # Dest Well, Vol (in ul) transfer_info = [[val.strip().lower() for val in line.split(',')] for line in transfer_csv.splitlines() if line.split(',')[0].strip()][1:] diff --git a/protocols/6d901d-2/README.md b/protocols/6d901d-2/README.md index 698cdc31b..b03c561a8 100644 --- a/protocols/6d901d-2/README.md +++ b/protocols/6d901d-2/README.md @@ -38,7 +38,7 @@ Explanation of complex parameters below: --- ### Labware -* Any verified labware found in our [Labware Library](https://labware.opentrons.com/?category=wellPlate) and some additional microplates (see plate options for source and destination plates parameters below, e.g. Greiner Bio-One plates) +* Any verified labware found in our [Labware Library](https://labware.opentrons.com/?category=wellPlate) and some additional microplates (see plate options for source and destination plates parameters below, e.g. Greiner Bio-One plates). ### Pipettes * [P20 Multi GEN2 Pipette](https://shop.opentrons.com/8-channel-electronic-pipette/) diff --git a/protocols/6d901d/6d901d.ot2.apiv2.py b/protocols/6d901d/6d901d.ot2.apiv2.py index 753ae3668..a2fc2507b 100644 --- a/protocols/6d901d/6d901d.ot2.apiv2.py +++ b/protocols/6d901d/6d901d.ot2.apiv2.py @@ -22,7 +22,7 @@ def flatten_matrix(m): def well_csv_to_list(csv_string): """ - Takes a csv string and flattens it to a list, re-ordering to match + Takes a csv string and flattens to a list, re-ordering to match Opentrons well order convention (A1, B1, C1, ..., A2, B2, B2, ...) """ data = [ diff --git a/protocols/6d901d/README.md b/protocols/6d901d/README.md index a1493160f..0d885f99f 100644 --- a/protocols/6d901d/README.md +++ b/protocols/6d901d/README.md @@ -20,7 +20,7 @@ Concentration Normalization is a key component of many genomic and proteomic app There is an optional [Part 2: Cherrypicking Protocol](https://protocols.opentrons.com/protocol/6d901d-2) to this protocol which performs cherrypicking using a multi-channel pipette in the same way. -**Note**: This protocol was updated for a change in our software stack and will require app 7.0 or greater. +**Note**: This protocol was updated for a change in our software stack and requires app 7.0 or greater. Using the customization fields below, set up your protocol. * `Volumes CSV`: Your input CSV specifying the normalization volumes. See the Setup section below for details.