From cb21eaadb531787a2a2d07ae4759d28c5e458f6d Mon Sep 17 00:00:00 2001 From: rclarke0 Date: Wed, 13 Nov 2024 11:32:32 -0500 Subject: [PATCH 1/4] create deck riser parameter --- .../12_KAPA HyperPlus Library Prep.py | 4 +- .../active_protocols/2_BMS_PCR_Protocol.py | 7 +++- .../3_OT3 ABR Normalize with Tubes.py | 1 - ...omplex protocol with single tip Pick Up.py | 4 +- .../protocols/csv_parameters/9_parameters.csv | 2 - abr-testing/abr_testing/protocols/helpers.py | 38 +++++++++++++++---- 6 files changed, 42 insertions(+), 14 deletions(-) delete mode 100644 abr-testing/abr_testing/protocols/csv_parameters/9_parameters.csv diff --git a/abr-testing/abr_testing/protocols/active_protocols/12_KAPA HyperPlus Library Prep.py b/abr-testing/abr_testing/protocols/active_protocols/12_KAPA HyperPlus Library Prep.py index 4563483b4ac..aa35efc3214 100644 --- a/abr-testing/abr_testing/protocols/active_protocols/12_KAPA HyperPlus Library Prep.py +++ b/abr-testing/abr_testing/protocols/active_protocols/12_KAPA HyperPlus Library Prep.py @@ -50,6 +50,7 @@ def add_parameters(parameters: ParameterContext) -> None: default=False, ) helpers.create_disposable_lid_parameter(parameters) + helpers.create_tc_lid_deck_riser_parameter(parameters) helpers.create_two_pipette_mount_parameters(parameters) parameters.add_int( variable_name="num_samples", @@ -85,6 +86,7 @@ def run(ctx: ProtocolContext) -> None: dry_run = ctx.params.dry_run # type: ignore[attr-defined] pipette_1000_mount = ctx.params.pipette_mount_1 # type: ignore[attr-defined] pipette_50_mount = ctx.params.pipette_mount_2 # type: ignore[attr-defined] + deck_riser = ctx.params.deck_riser # type: ignore[attr-defined] REUSE_ETOH_TIPS = True REUSE_RSB_TIPS = ( True # Reuse tips for RSB buffer (adding RSB, mixing, and transferring) @@ -158,7 +160,7 @@ def run(ctx: ProtocolContext) -> None: unused_lids: List[Labware] = [] # Load TC Lids if disposable_lid: - unused_lids = helpers.load_disposable_lids(ctx, 5, ["C3"]) + unused_lids = helpers.load_disposable_lids(ctx, 5, ["C3"], deck_riser) # Import Global Variables global tip50 diff --git a/abr-testing/abr_testing/protocols/active_protocols/2_BMS_PCR_Protocol.py b/abr-testing/abr_testing/protocols/active_protocols/2_BMS_PCR_Protocol.py index d044b5e8ed3..9598285b202 100644 --- a/abr-testing/abr_testing/protocols/active_protocols/2_BMS_PCR_Protocol.py +++ b/abr-testing/abr_testing/protocols/active_protocols/2_BMS_PCR_Protocol.py @@ -22,6 +22,7 @@ def add_parameters(parameters: ParameterContext) -> None: helpers.create_single_pipette_mount_parameter(parameters) helpers.create_disposable_lid_parameter(parameters) helpers.create_csv_parameter(parameters) + helpers.create_tc_lid_deck_riser_parameter(parameters) def run(ctx: ProtocolContext) -> None: @@ -29,6 +30,8 @@ def run(ctx: ProtocolContext) -> None: pipette_mount = ctx.params.pipette_mount # type: ignore[attr-defined] disposable_lid = ctx.params.disposable_lid # type: ignore[attr-defined] parsed_csv = ctx.params.parameters_csv.parse_as_csv() # type: ignore[attr-defined] + deck_riser = ctx.params.deck_riser # type: ignore[attr-defined] + rxn_vol = 50 real_mode = True # DECK SETUP AND LABWARE @@ -60,7 +63,7 @@ def run(ctx: ProtocolContext) -> None: # Opentrons tough pcr auto sealing lids if disposable_lid: - unused_lids = helpers.load_disposable_lids(ctx, 3, ["C3"]) + unused_lids = helpers.load_disposable_lids(ctx, 3, ["C3"], deck_riser) used_lids: List[Labware] = [] # LOAD PIPETTES @@ -205,4 +208,6 @@ def run(ctx: ProtocolContext) -> None: ctx.move_labware(lid_on_plate, "C2", use_gripper=True) else: ctx.move_labware(lid_on_plate, used_lids[-2], use_gripper=True) + p50.drop_tip() + p50.configure_nozzle_layout(style=SINGLE, start="A1", tip_racks=tiprack_50) helpers.find_liquid_height_of_all_wells(ctx, p50, wells_to_probe_flattened) diff --git a/abr-testing/abr_testing/protocols/active_protocols/3_OT3 ABR Normalize with Tubes.py b/abr-testing/abr_testing/protocols/active_protocols/3_OT3 ABR Normalize with Tubes.py index e25e4a6d7c8..1d044074430 100644 --- a/abr-testing/abr_testing/protocols/active_protocols/3_OT3 ABR Normalize with Tubes.py +++ b/abr-testing/abr_testing/protocols/active_protocols/3_OT3 ABR Normalize with Tubes.py @@ -340,5 +340,4 @@ def run(ctx: ProtocolContext) -> None: ) current += 1 - print(wells_with_liquids) helpers.find_liquid_height_of_all_wells(ctx, p50, wells_with_liquids) diff --git a/abr-testing/abr_testing/protocols/active_protocols/5_96ch complex protocol with single tip Pick Up.py b/abr-testing/abr_testing/protocols/active_protocols/5_96ch complex protocol with single tip Pick Up.py index 86801cfcc6e..a6fd544cae3 100644 --- a/abr-testing/abr_testing/protocols/active_protocols/5_96ch complex protocol with single tip Pick Up.py +++ b/abr-testing/abr_testing/protocols/active_protocols/5_96ch complex protocol with single tip Pick Up.py @@ -44,6 +44,7 @@ def add_parameters(parameters: ParameterContext) -> None: helpers.create_tip_size_parameter(parameters) helpers.create_dot_bottom_parameter(parameters) helpers.create_disposable_lid_parameter(parameters) + helpers.create_tc_lid_deck_riser_parameter(parameters) def run(ctx: ProtocolContext) -> None: @@ -51,6 +52,7 @@ def run(ctx: ProtocolContext) -> None: b = ctx.params.dot_bottom # type: ignore[attr-defined] TIPRACK_96_NAME = ctx.params.tip_size # type: ignore[attr-defined] disposable_lid = ctx.params.disposable_lid # type: ignore[attr-defined] + deck_riser = ctx.params.deck_riser # type: ignore[attr-defined] waste_chute = ctx.load_waste_chute() @@ -61,7 +63,7 @@ def run(ctx: ProtocolContext) -> None: helpers.temp_str, "C1" ) # type: ignore[assignment] if disposable_lid: - unused_lids = helpers.load_disposable_lids(ctx, 3, ["A4"]) + unused_lids = helpers.load_disposable_lids(ctx, 3, ["A4"], deck_riser) used_lids: List[Labware] = [] thermocycler.open_lid() h_s.open_labware_latch() diff --git a/abr-testing/abr_testing/protocols/csv_parameters/9_parameters.csv b/abr-testing/abr_testing/protocols/csv_parameters/9_parameters.csv deleted file mode 100644 index a5f947d97d5..00000000000 --- a/abr-testing/abr_testing/protocols/csv_parameters/9_parameters.csv +++ /dev/null @@ -1,2 +0,0 @@ -heater_shaker_speed, dot_bottom -2000, 0.1 \ No newline at end of file diff --git a/abr-testing/abr_testing/protocols/helpers.py b/abr-testing/abr_testing/protocols/helpers.py index c3b1b7f217d..9e525faa314 100644 --- a/abr-testing/abr_testing/protocols/helpers.py +++ b/abr-testing/abr_testing/protocols/helpers.py @@ -39,12 +39,24 @@ def load_common_liquid_setup_labware_and_instruments( def load_disposable_lids( - protocol: ProtocolContext, num_of_lids: int, deck_slot: List[str] + protocol: ProtocolContext, + num_of_lids: int, + deck_slot: List[str], + deck_riser: bool = False, ) -> List[Labware]: """Load Stack of Disposable lids.""" - unused_lids = [ - protocol.load_labware("opentrons_tough_pcr_auto_sealing_lid", deck_slot[0]) - ] + if deck_riser: + deck_riser_adapter = protocol.load_adapter( + "opentrons_flex_deck_riser", deck_slot[0] + ) + unused_lids = [ + deck_riser_adapter.load_labware("opentrons_tough_pcr_auto_sealing_lid") + ] + else: + unused_lids = [ + protocol.load_labware("opentrons_tough_pcr_auto_sealing_lid", deck_slot[0]) + ] + if len(deck_slot) == 1: for i in range(num_of_lids - 1): unused_lids.append( @@ -152,6 +164,16 @@ def create_disposable_lid_parameter(parameters: ParameterContext) -> None: ) +def create_tc_lid_deck_riser_parameter(parameters: ParameterContext) -> None: + """Create parameter for tc lid deck riser.""" + parameters.add_bool( + variable_name="deck_riser", + display_name="Deck Riser", + description="True means use deck riser.", + default=False, + ) + + def create_tip_size_parameter(parameters: ParameterContext) -> None: """Create parameter for tip size.""" parameters.add_str( @@ -334,10 +356,10 @@ def find_liquid_height_of_all_wells( """Find the liquid height of all wells in protocol.""" dict_of_labware_heights = {} pipette.pick_up_tip() + pip_channels = pipette.active_channels for well in wells: labware_name = well.parent.load_name total_number_of_wells_in_plate = len(well.parent.wells()) - pip_channels = pipette.active_channels # if pip_channels is > 1 and total_wells > 12 - only probe 1st row. if ( pip_channels > 1 @@ -349,11 +371,11 @@ def find_liquid_height_of_all_wells( elif total_number_of_wells_in_plate <= 12: liquid_height_of_well = find_liquid_height(pipette, well) dict_of_labware_heights[labware_name, well] = liquid_height_of_well - if pip_channels == pipette.channels: + if pip_channels != pipette.channels: + pipette.drop_tip() + else: pipette.return_tip() pipette.reset_tipracks() - else: - pipette.drop_tip() msg = f"result: {dict_of_labware_heights}" protocol.comment(msg=msg) return dict_of_labware_heights From 26b979b7c5e3a08a5407cdd76145e18525068407 Mon Sep 17 00:00:00 2001 From: Tony Ngumah Date: Wed, 20 Nov 2024 11:10:24 -0500 Subject: [PATCH 2/4] feat(abr_testing): added functionality to push one or more folders to one or more robots at the same time --- Makefile | 4 + abr-testing/abr_testing/tools/make_push.py | 87 ++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 abr-testing/abr_testing/tools/make_push.py diff --git a/Makefile b/Makefile index d3ddd15f359..7a5bfc7a7e9 100755 --- a/Makefile +++ b/Makefile @@ -152,6 +152,10 @@ push: sleep 1 $(MAKE) -C $(UPDATE_SERVER_DIR) push +.PHONY: push-folder +PUSH_HELPER := abr-testing/abr_testing/tools/make_push.py +push-folder: + $(OT_PYTHON) $(PUSH_HELPER) .PHONY: push-ot3 push-ot3: diff --git a/abr-testing/abr_testing/tools/make_push.py b/abr-testing/abr_testing/tools/make_push.py new file mode 100644 index 00000000000..e3e10c2e9e7 --- /dev/null +++ b/abr-testing/abr_testing/tools/make_push.py @@ -0,0 +1,87 @@ +import subprocess +import multiprocessing +import json +import time +global folders +# Opentrons folders that can be pushed to robot +folders = [ + 'abr-testing', + 'hardware-testing', + 'all', + 'other', +] + + + +def push_subroutine(cmd: str): + """Pushes specified folder to specified robot""" + try: + subprocess.run(cmd) + except Exception as e: + print('failed to push folder') + raise + +def main(folder_to_push: str, robot_to_push: str) -> int: + """Main process""" + cmd = 'make -C {folder} push-ot3 host={ip}' + robot_ip_path = "" + push_cmd = '' + folder_int = int(folder_to_push) + if folders[folder_int].lower() == 'all': + if robot_to_push.lower() == 'all': + robot_ip_path = input('Path to robot ips: ') + with open(robot_ip_path, 'r') as ip_file: + robot_json = json.load(ip_file) + robot_ips = robot_json.get('ip_address_list') + ip_file.close() + else: + robot_ips = [robot_to_push] + for folder_name in folders[:-2]: + #Push all folders to all robots + for robot in robot_ips: + print_proc = multiprocessing.Process(target=print, args=(f"Pushing {folder_name} to {robot}!\n\n",)) + print_proc.start() + print_proc.join() + push_cmd = cmd.format(folder=folder_name, ip=robot) + process = multiprocessing.Process(target=push_subroutine, args=(push_cmd,)) + process.start() + process.join() + print_proc = multiprocessing.Process(target=print, args=(f"Done!\n\n")) + print_proc.start() + print_proc.join() + else: + + if folder_int == (len(folders)-1): + folder_name = input('Which folder? ') + else: + folder_name = folders[folder_int] + if robot_to_push.lower() == 'all': + robot_ip_path = input("Path to robot ips: ") + with open(robot_ip_path, 'r') as ip_file: + robot_json = json.load(ip_file) + robot_ips = robot_json.get('ip_address_list') + ip_file.close() + else: + robot_ips = [robot_to_push] + + # Push folder to robots + for robot in robot_ips: + print_proc = multiprocessing.Process(target=print, args=(f"Pushing {folder_name} to {robot}!\n\n",)) + print_proc.start() + print_proc.join() + push_cmd = cmd.format(folder=folder_name, ip=robot) + process = multiprocessing.Process(target=push_subroutine, args=(push_cmd,)) + process.start() + process.join() + print_proc = multiprocessing.Process(target=print, args=(f"Done!\n\n",)) + print_proc.start() + print_proc.join() + return(0) + + +if __name__ == '__main__': + for i, folder in enumerate(folders): + print(f"{i}) {folder}") + folder_to_push = input('Please Select a Folder to Push: ') + robot_to_push = input("Type in robots ip (type all for all): ") + print(main(folder_to_push, robot_to_push)) \ No newline at end of file From 42768be2a2734826964f31a221be9323e47f078c Mon Sep 17 00:00:00 2001 From: Tony Ngumah Date: Wed, 20 Nov 2024 12:12:40 -0500 Subject: [PATCH 3/4] lint fixes --- abr-testing/abr_testing/tools/make_push.py | 80 ++++++++++++---------- 1 file changed, 44 insertions(+), 36 deletions(-) diff --git a/abr-testing/abr_testing/tools/make_push.py b/abr-testing/abr_testing/tools/make_push.py index e3e10c2e9e7..7d3d67fce6c 100644 --- a/abr-testing/abr_testing/tools/make_push.py +++ b/abr-testing/abr_testing/tools/make_push.py @@ -1,87 +1,95 @@ +"""Push one or more folders to one or more robots.""" import subprocess import multiprocessing import json -import time + global folders # Opentrons folders that can be pushed to robot folders = [ - 'abr-testing', - 'hardware-testing', - 'all', - 'other', + "abr-testing", + "hardware-testing", + "all", + "other", ] - -def push_subroutine(cmd: str): - """Pushes specified folder to specified robot""" +def push_subroutine(cmd: str) -> None: + """Pushes specified folder to specified robot.""" try: subprocess.run(cmd) - except Exception as e: - print('failed to push folder') + except Exception: + print("failed to push folder") raise - + + def main(folder_to_push: str, robot_to_push: str) -> int: - """Main process""" - cmd = 'make -C {folder} push-ot3 host={ip}' + """Main process!""" + cmd = "make -C {folder} push-ot3 host={ip}" robot_ip_path = "" - push_cmd = '' + push_cmd = "" folder_int = int(folder_to_push) - if folders[folder_int].lower() == 'all': - if robot_to_push.lower() == 'all': - robot_ip_path = input('Path to robot ips: ') - with open(robot_ip_path, 'r') as ip_file: + if folders[folder_int].lower() == "all": + if robot_to_push.lower() == "all": + robot_ip_path = input("Path to robot ips: ") + with open(robot_ip_path, "r") as ip_file: robot_json = json.load(ip_file) - robot_ips = robot_json.get('ip_address_list') + robot_ips_dict = robot_json.get("ip_address_list") + robot_ips = list(robot_ips_dict.keys()) ip_file.close() else: robot_ips = [robot_to_push] for folder_name in folders[:-2]: - #Push all folders to all robots + # Push all folders to all robots for robot in robot_ips: - print_proc = multiprocessing.Process(target=print, args=(f"Pushing {folder_name} to {robot}!\n\n",)) + print_proc = multiprocessing.Process( + target=print, args=(f"Pushing {folder_name} to {robot}!\n\n",) + ) print_proc.start() print_proc.join() push_cmd = cmd.format(folder=folder_name, ip=robot) - process = multiprocessing.Process(target=push_subroutine, args=(push_cmd,)) + process = multiprocessing.Process( + target=push_subroutine, args=(push_cmd,) + ) process.start() process.join() - print_proc = multiprocessing.Process(target=print, args=(f"Done!\n\n")) + print_proc = multiprocessing.Process(target=print, args=("Done!\n\n")) print_proc.start() print_proc.join() else: - - if folder_int == (len(folders)-1): - folder_name = input('Which folder? ') + + if folder_int == (len(folders) - 1): + folder_name = input("Which folder? ") else: folder_name = folders[folder_int] - if robot_to_push.lower() == 'all': + if robot_to_push.lower() == "all": robot_ip_path = input("Path to robot ips: ") - with open(robot_ip_path, 'r') as ip_file: + with open(robot_ip_path, "r") as ip_file: robot_json = json.load(ip_file) - robot_ips = robot_json.get('ip_address_list') + robot_ips = robot_json.get("ip_address_list") ip_file.close() else: robot_ips = [robot_to_push] # Push folder to robots for robot in robot_ips: - print_proc = multiprocessing.Process(target=print, args=(f"Pushing {folder_name} to {robot}!\n\n",)) + print_proc = multiprocessing.Process( + target=print, args=(f"Pushing {folder_name} to {robot}!\n\n",) + ) print_proc.start() print_proc.join() push_cmd = cmd.format(folder=folder_name, ip=robot) process = multiprocessing.Process(target=push_subroutine, args=(push_cmd,)) process.start() process.join() - print_proc = multiprocessing.Process(target=print, args=(f"Done!\n\n",)) + print_proc = multiprocessing.Process(target=print, args=("Done!\n\n",)) print_proc.start() print_proc.join() - return(0) + return 0 + - -if __name__ == '__main__': +if __name__ == "__main__": for i, folder in enumerate(folders): print(f"{i}) {folder}") - folder_to_push = input('Please Select a Folder to Push: ') + folder_to_push = input("Please Select a Folder to Push: ") robot_to_push = input("Type in robots ip (type all for all): ") - print(main(folder_to_push, robot_to_push)) \ No newline at end of file + print(main(folder_to_push, robot_to_push)) From 1762be569ee0f0ad94f36d8d9d7747cb7d1eef5e Mon Sep 17 00:00:00 2001 From: Tony Ngumah Date: Thu, 21 Nov 2024 10:19:48 -0500 Subject: [PATCH 4/4] modified make push prompts --- abr-testing/abr_testing/tools/make_push.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/abr-testing/abr_testing/tools/make_push.py b/abr-testing/abr_testing/tools/make_push.py index 7d3d67fce6c..28a69b11103 100644 --- a/abr-testing/abr_testing/tools/make_push.py +++ b/abr-testing/abr_testing/tools/make_push.py @@ -8,7 +8,7 @@ folders = [ "abr-testing", "hardware-testing", - "all", + "abr-testing + hardware-testing", "other", ] @@ -28,7 +28,7 @@ def main(folder_to_push: str, robot_to_push: str) -> int: robot_ip_path = "" push_cmd = "" folder_int = int(folder_to_push) - if folders[folder_int].lower() == "all": + if folders[folder_int].lower() == "abr-testing + hardware-testing": if robot_to_push.lower() == "all": robot_ip_path = input("Path to robot ips: ") with open(robot_ip_path, "r") as ip_file: @@ -39,7 +39,7 @@ def main(folder_to_push: str, robot_to_push: str) -> int: else: robot_ips = [robot_to_push] for folder_name in folders[:-2]: - # Push all folders to all robots + # Push abr-testing and hardware-testing folders to all robots for robot in robot_ips: print_proc = multiprocessing.Process( target=print, args=(f"Pushing {folder_name} to {robot}!\n\n",) @@ -52,7 +52,7 @@ def main(folder_to_push: str, robot_to_push: str) -> int: ) process.start() process.join() - print_proc = multiprocessing.Process(target=print, args=("Done!\n\n")) + print_proc = multiprocessing.Process(target=print, args=("Done!\n\n",)) print_proc.start() print_proc.join() else: