Skip to content

Commit

Permalink
Merge pull request #4824 from Opentrons/feat-5eee17_volume
Browse files Browse the repository at this point in the history
feat(protocols/5eee17): add field for dilution volume
  • Loading branch information
ncdiehl11 authored Aug 8, 2023
2 parents 6e5c0ed + 253fef2 commit 93ee272
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 15 deletions.
1 change: 1 addition & 0 deletions data/data/fields.csv
Original file line number Diff line number Diff line change
Expand Up @@ -1602,6 +1602,7 @@ vol_deaddeepwell,1
vol_deadreservoir,1
vol_dil_to_d,1
vol_dil_to_e,1
vol_dilution,1
vol_dispense,1
vol_dispensed,1
vol_dna,2
Expand Down
18 changes: 12 additions & 6 deletions protoBuilds/5eee17/dilution.ot2.apiv2.py.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"content": "import math\n\nmetadata = {\n 'protocolName': 'HPLC Dilution',\n 'author': 'Nick Diehl <[email protected]>',\n 'source': 'Custom Protocol Request',\n 'apiLevel': '2.12'\n}\n\n\ndef run(ctx):\n\n [num_extracts, lw_hplc, mixreps_dilution, height_source,\n height_intermediate_low, height_intermediate_middle,\n height_intermediate_high, height_final] = get_values( # noqa: F821\n 'num_extracts', 'lw_hplc', 'mixreps_dilution', 'height_source',\n 'height_intermediate_low', 'height_intermediate_middle',\n 'height_intermediate_high', 'height_final')\n\n tuberacks_50 = [\n ctx.load_labware('bd_24_tuberack_50ml_green', slot, '50ml tubes')\n for slot in ['1', '2']]\n tuberack_15 = ctx.load_labware('bd_72_tuberack_15ml_orange', '3')\n tuberack_hplc = ctx.load_labware(lw_hplc, '11', 'HPLC tuberack')\n tiprack = [ctx.load_labware('opentrons_96_tiprack_1000ul', '10')]\n p1000l, p1000r = [\n ctx.load_instrument('p1000_single_gen2', mount, tip_racks=tiprack)\n for mount in ['left', 'right']]\n pips = [p1000l, p1000r]\n\n tip_max = len([well for rack in tiprack for well in rack.wells()])\n tip_count = 0\n\n def pick_up(pipettes):\n nonlocal tip_count\n for pip in pipettes:\n if tip_count == tip_max:\n ctx.pause('Refill tiprack before resuming.')\n [rack.reset() for rack in tiprack]\n tip_count = 0\n tip_count += 1\n pip.pick_up_tip()\n\n mix_height_list = [height_intermediate_low, height_intermediate_middle,\n height_intermediate_high]\n\n def mix(pip, reps, vol, loc):\n p1000r.flow_rate.aspirate *= 6\n p1000l.flow_rate.aspirate *= 6\n p1000r.flow_rate.dispense *= 3\n p1000l.flow_rate.dispense *= 3\n for rep_ind in range(reps):\n asp_ind = (rep_ind*2) % 3\n disp_ind = (rep_ind*2+1) % 3\n pip.aspirate(vol, loc.bottom(mix_height_list[asp_ind]))\n pip.dispense(vol, loc.bottom(mix_height_list[disp_ind]))\n p1000r.flow_rate.aspirate /= 6\n p1000l.flow_rate.aspirate /= 6\n p1000r.flow_rate.dispense /= 3\n p1000l.flow_rate.dispense /= 3\n\n refill_map = {\n 'source': len(\n [well for rack in tuberacks_50 for well in rack.wells()]),\n 'intermediate': len(tuberack_15.wells()),\n 'final': len(tuberack_hplc.wells())\n }\n\n def check_refill(index):\n refill_items = []\n for key, val in refill_map.items():\n if index % val == 0 and index > 0:\n refill_items.append(key)\n if len(refill_items) > 0:\n ctx.pause(f'Please refill {\", \".join(refill_items)} tubes before \\\nresuming.')\n\n def get_set_index(set_index, tubes_set_type):\n set_index_transform = set_index % \\\n math.floor(refill_map[tubes_set_type]/2)\n return set_index_transform\n\n sources = [\n well for rack in tuberacks_50\n for well in rack.wells()]\n source_sets = [\n sources[i*2:(i+1)*2] if i < math.ceil(len(sources)/2)\n else sources[i*2:]\n for i in range(math.ceil(len(sources)/2))]\n intermediates = [\n well for col in tuberack_15.columns()\n for well in col]\n intermediate_sets = [\n intermediates[i*2:(i+1)*2]\n if i < math.ceil(len(intermediates)/2) - 1\n else intermediates[i*2:]\n for i in range(math.ceil(len(intermediates)/2))]\n finals = [\n well for row in tuberack_hplc.rows()\n for well in row]\n final_sets = [\n finals[i*2:(i+1)*2] if i < math.ceil(len(finals)/2) - 1\n else finals[i*2:]\n for i in range(math.ceil(len(finals)/2))]\n\n # dilute\n num_sets = math.ceil(num_extracts/2)\n for set_ind in range(num_sets):\n check_refill(set_ind*2)\n source_set = source_sets[get_set_index(set_ind, 'source')]\n intermediate_set = intermediate_sets[\n get_set_index(set_ind, 'intermediate')]\n final_set = final_sets[get_set_index(set_ind, 'final')]\n pick_up([p1000l, p1000r][:len(source_set)])\n\n for pip, tube in zip(pips, source_set):\n pip.aspirate(500, tube.bottom(height_source))\n pip.air_gap(100)\n\n for pip, i_tube, f_tube in zip(pips, intermediate_set, final_set):\n pip.dispense(100, i_tube.top())\n pip.dispense(pip.current_volume,\n i_tube.bottom(height_intermediate_middle))\n mix(pip, mixreps_dilution, 1000, i_tube)\n pip.transfer(800, i_tube.bottom(height_intermediate_low),\n f_tube.bottom(height_final),\n new_tip='never')\n [pip.drop_tip() for pip in [p1000l, p1000r] if pip.has_tip]\n",
"content": "import math\n\nmetadata = {\n 'protocolName': 'HPLC Dilution',\n 'author': 'Nick Diehl <[email protected]>',\n 'source': 'Custom Protocol Request',\n 'apiLevel': '2.12'\n}\n\n\ndef run(ctx):\n\n [num_extracts, lw_hplc, vol_dilution, mixreps_dilution, height_source,\n height_intermediate_low, height_intermediate_middle,\n height_intermediate_high, height_final] = get_values( # noqa: F821\n 'num_extracts', 'lw_hplc', 'vol_dilution', 'mixreps_dilution',\n 'height_source', 'height_intermediate_low',\n 'height_intermediate_middle', 'height_intermediate_high',\n 'height_final')\n\n tuberacks_50 = [\n ctx.load_labware('bd_24_tuberack_50ml_green', slot, '50ml tubes')\n for slot in ['1', '2']]\n tuberack_15 = ctx.load_labware('bd_72_tuberack_15ml_orange', '3')\n tuberack_hplc = ctx.load_labware(lw_hplc, '11', 'HPLC tuberack')\n tiprack = [ctx.load_labware('opentrons_96_tiprack_1000ul', '10')]\n p1000l, p1000r = [\n ctx.load_instrument('p1000_single_gen2', mount, tip_racks=tiprack)\n for mount in ['left', 'right']]\n pips = [p1000l, p1000r]\n\n tip_max = len([well for rack in tiprack for well in rack.wells()])\n tip_count = 0\n\n def pick_up(pipettes):\n nonlocal tip_count\n for pip in pipettes:\n if tip_count == tip_max:\n ctx.pause('Refill tiprack before resuming.')\n [rack.reset() for rack in tiprack]\n tip_count = 0\n tip_count += 1\n pip.pick_up_tip()\n\n mix_height_list = [height_intermediate_low, height_intermediate_middle,\n height_intermediate_high]\n\n def mix(pip, reps, vol, loc):\n p1000r.flow_rate.aspirate *= 6\n p1000l.flow_rate.aspirate *= 6\n p1000r.flow_rate.dispense *= 3\n p1000l.flow_rate.dispense *= 3\n for rep_ind in range(reps):\n asp_ind = (rep_ind*2) % 3\n disp_ind = (rep_ind*2+1) % 3\n pip.aspirate(vol, loc.bottom(mix_height_list[asp_ind]))\n pip.dispense(vol, loc.bottom(mix_height_list[disp_ind]))\n p1000r.flow_rate.aspirate /= 6\n p1000l.flow_rate.aspirate /= 6\n p1000r.flow_rate.dispense /= 3\n p1000l.flow_rate.dispense /= 3\n\n refill_map = {\n 'source': len(\n [well for rack in tuberacks_50 for well in rack.wells()]),\n 'intermediate': len(tuberack_15.wells()),\n 'final': len(tuberack_hplc.wells())\n }\n\n def check_refill(index):\n refill_items = []\n for key, val in refill_map.items():\n if index % val == 0 and index > 0:\n refill_items.append(key)\n if len(refill_items) > 0:\n ctx.pause(f'Please refill {\", \".join(refill_items)} tubes before \\\nresuming.')\n\n def get_set_index(set_index, tubes_set_type):\n set_index_transform = set_index % \\\n math.floor(refill_map[tubes_set_type]/2)\n return set_index_transform\n\n sources = [\n well for rack in tuberacks_50\n for well in rack.wells()]\n source_sets = [\n sources[i*2:(i+1)*2] if i < math.ceil(len(sources)/2)\n else sources[i*2:]\n for i in range(math.ceil(len(sources)/2))]\n intermediates = [\n well for col in tuberack_15.columns()\n for well in col]\n intermediate_sets = [\n intermediates[i*2:(i+1)*2]\n if i < math.ceil(len(intermediates)/2) - 1\n else intermediates[i*2:]\n for i in range(math.ceil(len(intermediates)/2))]\n finals = [\n well for row in tuberack_hplc.rows()\n for well in row]\n final_sets = [\n finals[i*2:(i+1)*2] if i < math.ceil(len(finals)/2) - 1\n else finals[i*2:]\n for i in range(math.ceil(len(finals)/2))]\n\n # dilute\n num_sets = math.ceil(num_extracts/2)\n for set_ind in range(num_sets):\n check_refill(set_ind*2)\n source_set = source_sets[get_set_index(set_ind, 'source')]\n intermediate_set = intermediate_sets[\n get_set_index(set_ind, 'intermediate')]\n final_set = final_sets[get_set_index(set_ind, 'final')]\n pick_up([p1000l, p1000r][:len(source_set)])\n\n for pip, tube in zip(pips, source_set):\n pip.aspirate(500, tube.bottom(height_source))\n pip.air_gap(100)\n\n for pip, i_tube, f_tube in zip(pips, intermediate_set, final_set):\n pip.dispense(100, i_tube.top())\n pip.dispense(pip.current_volume,\n i_tube.bottom(height_intermediate_middle))\n mix(pip, mixreps_dilution, 1000, i_tube)\n pip.transfer(800, i_tube.bottom(height_intermediate_low),\n f_tube.bottom(height_final),\n new_tip='never')\n [pip.drop_tip() for pip in [p1000l, p1000r] if pip.has_tip]\n",
"custom_labware_defs": [
{
"brand": {
Expand Down Expand Up @@ -2458,6 +2458,12 @@
],
"type": "dropDown"
},
{
"default": 500.0,
"label": "dilution volume (in ul)",
"name": "vol_dilution",
"type": "float"
},
{
"default": 5,
"label": "mix repetitions of dilution",
Expand All @@ -2468,31 +2474,31 @@
"default": 5.0,
"label": "source 50ml tube aspiration height (in mm above bottom)",
"name": "height_source",
"type": "int"
"type": "float"
},
{
"default": 5.0,
"label": "dilution 15ml tube low mix height (in mm above bottom)",
"name": "height_intermediate_low",
"type": "int"
"type": "float"
},
{
"default": 30.0,
"label": "dilution 15ml tube middle mix height (in mm above bottom)",
"name": "height_intermediate_middle",
"type": "int"
"type": "float"
},
{
"default": 60.0,
"label": "dilution 15ml tube high mix height (in mm above bottom)",
"name": "height_intermediate_high",
"type": "int"
"type": "float"
},
{
"default": 5.0,
"label": "final HPLC tube dispense height (in mm above bottom)",
"name": "height_final",
"type": "int"
"type": "float"
}
],
"instruments": [
Expand Down
9 changes: 5 additions & 4 deletions protocols/5eee17/dilution.ot2.apiv2.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@

def run(ctx):

[num_extracts, lw_hplc, mixreps_dilution, height_source,
[num_extracts, lw_hplc, vol_dilution, mixreps_dilution, height_source,
height_intermediate_low, height_intermediate_middle,
height_intermediate_high, height_final] = get_values( # noqa: F821
'num_extracts', 'lw_hplc', 'mixreps_dilution', 'height_source',
'height_intermediate_low', 'height_intermediate_middle',
'height_intermediate_high', 'height_final')
'num_extracts', 'lw_hplc', 'vol_dilution', 'mixreps_dilution',
'height_source', 'height_intermediate_low',
'height_intermediate_middle', 'height_intermediate_high',
'height_final')

tuberacks_50 = [
ctx.load_labware('bd_24_tuberack_50ml_green', slot, '50ml tubes')
Expand Down
16 changes: 11 additions & 5 deletions protocols/5eee17/fields.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,38 +14,44 @@
{"label": "blue", "value": "bd_48_tuberack_5ml_blue"}
]
},
{
"type": "float",
"label": "dilution volume (in ul)",
"name": "vol_dilution",
"default": 500.0
},
{
"type": "int",
"label": "mix repetitions of dilution",
"name": "mixreps_dilution",
"default": 5
},
{
"type": "int",
"type": "float",
"label": "source 50ml tube aspiration height (in mm above bottom)",
"name": "height_source",
"default": 5.0
},
{
"type": "int",
"type": "float",
"label": "dilution 15ml tube low mix height (in mm above bottom)",
"name": "height_intermediate_low",
"default": 5.0
},
{
"type": "int",
"type": "float",
"label": "dilution 15ml tube middle mix height (in mm above bottom)",
"name": "height_intermediate_middle",
"default": 30.0
},
{
"type": "int",
"type": "float",
"label": "dilution 15ml tube high mix height (in mm above bottom)",
"name": "height_intermediate_high",
"default": 60.0
},
{
"type": "int",
"type": "float",
"label": "final HPLC tube dispense height (in mm above bottom)",
"name": "height_final",
"default": 5.0
Expand Down

0 comments on commit 93ee272

Please sign in to comment.