From 82aef48e50a9c57f9127d7f5794755dc5a31374a Mon Sep 17 00:00:00 2001 From: Rhyann Clarke <146747548+rclarke0@users.noreply.github.com> Date: Wed, 18 Dec 2024 11:31:56 -0500 Subject: [PATCH] feat (abr-testing): Lengthen ABR Protocols, Add Protocol Versioning, Add Liquid Waste Probing and Recording (#17137) # Overview ABR Protocol Improvements: Lengthen protocols, Add Version numbers, Add Liquid Waste Probing ## Test Plan and Hands on Testing Protocols have been running for ~ 2-5 days depending on the robot to ensure functionality ## Changelog - The protocol version number is commented at the beginning of the protocol and recorded in the ABR google sheet - All protocols now have a clean up step to move all liquids into liquid waste - At the end of the protocol the liquid waste liquid height is measured in the ABR google sheet ## Review requests ## Risk assessment --------- Co-authored-by: Tony Ngumah --- .../data_collection/abr_google_drive.py | 31 +- .../data_collection/abr_robot_error.py | 14 +- .../data_collection/read_robot_logs.py | 70 +- .../data_collection/single_run_log_reader.py | 5 +- .../10_ZymoBIOMICS_Magbead_DNA_Cells_Flex.py | 222 ++-- .../11_Dynabeads_IP_Flex_96well_RIT.py | 212 ++-- .../12_KAPA HyperPlus Library Prep.py | 300 ++--- .../1_Simple Normalize Long Right.py | 288 +++-- .../active_protocols/2_BMS_PCR_Protocol.py | 108 +- .../active_protocols/3_Tartrazine Protocol.py | 206 +++- .../4_Illumina DNA Enrichment.py | 1016 +++++++++++++++++ ...omplex protocol with single tip Pick Up.py | 188 +-- .../6_Omega_HDQ_DNA_Cells-Flex_96_channel.py | 301 +++-- .../7_HDQ_DNA_Bacteria_Flex.py | 115 +- .../8_Illumina and Plate Reader.py | 158 ++- .../9_Magmax_RNA_Cells_Flex.py | 257 +++-- .../protocols/csv_parameters/1_samplevols.csv | 97 ++ .../protocols/csv_parameters/2_samplevols.csv | 96 +- abr-testing/abr_testing/protocols/helpers.py | 180 ++- .../10_ZymoBIOMICS Magbead Liquid Setup.py | 31 +- .../11_Dynabeads RIT Liquid Setup.py | 25 +- ...APA HyperPlus Library Prep Liquid Setup.py | 2 +- .../1_Simple normalize long Liquid Setup.py | 14 +- .../2_BMS_PCR_protocol Liquid Setup.py | 10 +- .../3_Tartrazine Liquid Setup.py | 91 +- .../4_Illumina DNA Enrichment Liquid Setup.py | 25 +- .../5_96ch Complex Protocol Liquid Setup.py | 10 +- ...DQ DNA Bacteria Extraction Liquid Setup.py | 34 +- ...ermo MagMax RNA Extraction Liquid Setup.py | 49 +- .../test_protocols/tc_lid_x_offset_test.py | 14 +- abr-testing/abr_testing/tools/abr_scale.py | 14 +- abr-testing/abr_testing/tools/abr_setup.py | 8 +- 32 files changed, 2993 insertions(+), 1198 deletions(-) create mode 100644 abr-testing/abr_testing/protocols/active_protocols/4_Illumina DNA Enrichment.py create mode 100644 abr-testing/abr_testing/protocols/csv_parameters/1_samplevols.csv diff --git a/abr-testing/abr_testing/data_collection/abr_google_drive.py b/abr-testing/abr_testing/data_collection/abr_google_drive.py index 8f82567a7d1..655200745a9 100644 --- a/abr-testing/abr_testing/data_collection/abr_google_drive.py +++ b/abr-testing/abr_testing/data_collection/abr_google_drive.py @@ -34,16 +34,13 @@ def create_data_dictionary( runs_to_save: Union[Set[str], str], storage_directory: str, issue_url: str, - plate: str, - accuracy: Any, hellma_plate_standards: List[Dict[str, Any]], -) -> Tuple[List[List[Any]], List[str], List[List[Any]], List[str], List[List[Any]]]: +) -> Tuple[List[List[Any]], List[str], List[List[Any]], List[str]]: """Pull data from run files and format into a dictionary.""" runs_and_robots: List[Any] = [] runs_and_lpc: List[Dict[str, Any]] = [] headers: List[str] = [] headers_lpc: List[str] = [] - list_of_heights: List[List[Any]] = [[], [], [], [], [], [], [], []] hellma_plate_orientation = False # default hellma plate is not rotated. for filename in os.listdir(storage_directory): file_path = os.path.join(storage_directory, filename) @@ -103,12 +100,15 @@ def create_data_dictionary( run_time_min = run_time.total_seconds() / 60 except ValueError: pass # Handle datetime parsing errors if necessary + # Get protocol version # + version_number = read_robot_logs.get_protocol_version_number(file_results) if run_time_min > 0: run_row = { "Robot": robot, "Run_ID": run_id, "Protocol_Name": protocol_name, + "Protocol Version": version_number, "Software Version": software_version, "Date": start_date, "Start_Time": start_time_str, @@ -130,13 +130,10 @@ def create_data_dictionary( plate_reader_dict = read_robot_logs.plate_reader_commands( file_results, hellma_plate_standards, hellma_plate_orientation ) - list_of_heights = read_robot_logs.liquid_height_commands( - file_results, list_of_heights - ) notes = {"Note1": "", "Jira Link": issue_url} + liquid_height = read_robot_logs.get_liquid_waste_height(file_results) plate_measure = { - "Plate Measured": plate, - "End Volume Accuracy (%)": accuracy, + "Liquid Waste Height (mm)": liquid_height, "Average Temp (oC)": "", "Average RH(%)": "", } @@ -173,7 +170,6 @@ def create_data_dictionary( headers, transposed_runs_and_lpc, headers_lpc, - list_of_heights, ) @@ -211,26 +207,15 @@ def run( headers, transposed_runs_and_lpc, headers_lpc, - list_of_heights, ) = create_data_dictionary( missing_runs_from_gs, storage_directory, "", - "", - "", - hellma_plate_standards=file_values, + file_values, ) start_row = google_sheet.get_index_row() + 1 google_sheet.batch_update_cells(transposed_runs_and_robots, "A", start_row, "0") - # Record Liquid Heights Found - google_sheet_ldf = google_sheets_tool.google_sheet( - credentials_path, google_sheet_name, 2 - ) - google_sheet_ldf.get_row(1) - start_row_lhd = google_sheet_ldf.get_index_row() + 1 - google_sheet_ldf.batch_update_cells( - list_of_heights, "A", start_row_lhd, "2075262446" - ) + # Add LPC to google sheet google_sheet_lpc = google_sheets_tool.google_sheet(credentials_path, "ABR-LPC", 0) start_row_lpc = google_sheet_lpc.get_index_row() + 1 diff --git a/abr-testing/abr_testing/data_collection/abr_robot_error.py b/abr-testing/abr_testing/data_collection/abr_robot_error.py index 75e6bcde34e..c2dadaae54c 100644 --- a/abr-testing/abr_testing/data_collection/abr_robot_error.py +++ b/abr-testing/abr_testing/data_collection/abr_robot_error.py @@ -667,28 +667,16 @@ def get_run_error_info_from_robot( headers, runs_and_lpc, headers_lpc, - list_of_heights, ) = abr_google_drive.create_data_dictionary( run_id, error_folder_path, issue_url, - "", - "", - hellma_plate_standards=file_values, + file_values, ) start_row = google_sheet.get_index_row() + 1 google_sheet.batch_update_cells(runs_and_robots, "A", start_row, "0") print("Wrote run to ABR-run-data") - # Record Liquid Heights Found - google_sheet_ldf = google_sheets_tool.google_sheet( - credentials_path, google_sheet_name, 4 - ) - start_row_lhd = google_sheet_ldf.get_index_row() + 1 - google_sheet_ldf.batch_update_cells( - list_of_heights, "A", start_row_lhd, "1795535088" - ) - print("wrote liquid heights found.") # Add LPC to google sheet google_sheet_lpc = google_sheets_tool.google_sheet( credentials_path, "ABR-LPC", 0 diff --git a/abr-testing/abr_testing/data_collection/read_robot_logs.py b/abr-testing/abr_testing/data_collection/read_robot_logs.py index 7bc83e0a54b..0a098835cf7 100644 --- a/abr-testing/abr_testing/data_collection/read_robot_logs.py +++ b/abr-testing/abr_testing/data_collection/read_robot_logs.py @@ -134,7 +134,8 @@ def match_pipette_to_action( left_pipette_add = 0 for command in commandTypes: command_type = command_dict["commandType"] - command_pipette = command_dict.get("pipetteId", "") + command_params = command_dict.get("params", "") + command_pipette = command_params.get("pipetteId", "") if command_type == command and command_pipette == right_pipette: right_pipette_add = 1 elif command_type == command and command_pipette == left_pipette: @@ -213,6 +214,35 @@ def instrument_commands( return pipette_dict +def get_comment_result_by_string(file_results: Dict[str, Any], key_phrase: str) -> str: + """Get comment string based off ky phrase.""" + commandData = file_results.get("commands", "") + result_str = command_str = "" + for command in commandData: + commandType = command["commandType"] + if commandType == "comment": + command_str = command["params"].get("message", "") + try: + result_str = command_str.split(key_phrase)[1] + except IndexError: + continue + return result_str + + +def get_protocol_version_number(file_results: Dict[str, Any]) -> str: + """Get protocol version number.""" + return get_comment_result_by_string(file_results, "Protocol Version: ") + + +def get_liquid_waste_height(file_results: Dict[str, Any]) -> float: + """Find liquid waste height.""" + result_str = get_comment_result_by_string( + file_results, "Liquid Waste Total Height: " + ) + height = float(result_str) + return height + + def liquid_height_commands( file_results: Dict[str, Any], all_heights_list: List[List[Any]] ) -> List[List[Any]]: @@ -220,6 +250,9 @@ def liquid_height_commands( commandData = file_results.get("commands", "") robot = file_results.get("robot_name", "") run_id = file_results.get("run_id", "") + list_of_heights = [] + print(robot) + liquid_waste_height = 0.0 for command in commandData: commandType = command["commandType"] if commandType == "comment": @@ -236,16 +269,24 @@ def liquid_height_commands( well_location = str(entry.split(", ")[1].split(" ")[0]) slot_location = str(entry.split("slot ")[1].split(")")[0]) labware_name = str(entry.split("of ")[1].split(" on")[0]) - all_heights_list[0].append(robot) - all_heights_list[1].append(run_id) - all_heights_list[2].append(comment_time) - all_heights_list[3].append(labware_type) - all_heights_list[4].append(labware_name) - all_heights_list[5].append(slot_location) - all_heights_list[6].append(well_location) - all_heights_list[7].append(height) + if labware_name == "Liquid Waste": + liquid_waste_height += height + one_entry = { + "Timestamp": comment_time, + "Labware Name": labware_name, + "Labware Type": labware_type, + "Slot Location": slot_location, + "Well Location": well_location, + "All Heights (mm)": height, + } + list_of_heights.append(one_entry) except (IndexError, ValueError): continue + if len(list_of_heights) > 0: + all_heights_list[0].append(robot) + all_heights_list[1].append(run_id) + all_heights_list[2].append(list_of_heights) + all_heights_list[3].append(liquid_waste_height) return all_heights_list @@ -281,10 +322,13 @@ def plate_reader_commands( read = "yes" elif read == "yes" and commandType == "comment": result = command["params"].get("message", "") - if "result:" in result: - plate_name = result.split("result:")[0] - formatted_result = result.split("result: ")[1] - print(formatted_result) + if "result:" in result or "Result:" in result: + try: + plate_name = result.split("result:")[0] + formatted_result = result.split("result: ")[1] + except IndexError: + plate_name = result.split("Result:")[0] + formatted_result = result.split("Result: ")[1] result_dict = eval(formatted_result) result_dict_keys = list(result_dict.keys()) if len(result_dict_keys) > 1: diff --git a/abr-testing/abr_testing/data_collection/single_run_log_reader.py b/abr-testing/abr_testing/data_collection/single_run_log_reader.py index a61670e6d12..bf10347faff 100644 --- a/abr-testing/abr_testing/data_collection/single_run_log_reader.py +++ b/abr-testing/abr_testing/data_collection/single_run_log_reader.py @@ -34,14 +34,11 @@ header, runs_and_lpc, lpc_headers, - list_of_heights, ) = abr_google_drive.create_data_dictionary( run_ids_in_storage, run_log_file_path, "", - "", - "", - hellma_plate_standards=file_values, + file_values, ) print("list_of_heights not recorded.") transposed_list = list(zip(*runs_and_robots)) diff --git a/abr-testing/abr_testing/protocols/active_protocols/10_ZymoBIOMICS_Magbead_DNA_Cells_Flex.py b/abr-testing/abr_testing/protocols/active_protocols/10_ZymoBIOMICS_Magbead_DNA_Cells_Flex.py index 9631b442694..9e93e597bbd 100644 --- a/abr-testing/abr_testing/protocols/active_protocols/10_ZymoBIOMICS_Magbead_DNA_Cells_Flex.py +++ b/abr-testing/abr_testing/protocols/active_protocols/10_ZymoBIOMICS_Magbead_DNA_Cells_Flex.py @@ -17,7 +17,7 @@ "protocolName": "Flex ZymoBIOMICS Magbead DNA Extraction: Cells", } -requirements = {"robotType": "OT-3", "apiLevel": "2.21"} +requirements = {"robotType": "Flex", "apiLevel": "2.21"} """ Slot A1: Tips 1000 Slot A2: Tips 1000 @@ -41,11 +41,12 @@ Wells 1-12 - 9,000 ul """ -whichwash = 1 +whichwash = 0 +wash_volume_tracker = 0.0 sample_max = 48 tip1k = 0 -tip200 = 0 drop_count = 0 +m1000_tips = 0 def add_parameters(parameters: protocol_api.ParameterContext) -> None: @@ -53,28 +54,40 @@ def add_parameters(parameters: protocol_api.ParameterContext) -> None: helpers.create_hs_speed_parameter(parameters) helpers.create_single_pipette_mount_parameter(parameters) helpers.create_dot_bottom_parameter(parameters) + helpers.create_deactivate_modules_parameter(parameters) -def run(ctx: protocol_api.ProtocolContext) -> None: +def run(protocol: protocol_api.ProtocolContext) -> None: """Protocol Set Up.""" - heater_shaker_speed = ctx.params.heater_shaker_speed # type: ignore[attr-defined] - mount = ctx.params.pipette_mount # type: ignore[attr-defined] - dot_bottom = ctx.params.dot_bottom # type: ignore[attr-defined] + heater_shaker_speed = protocol.params.heater_shaker_speed # type: ignore[attr-defined] + mount = protocol.params.pipette_mount # type: ignore[attr-defined] + dot_bottom = protocol.params.dot_bottom # type: ignore[attr-defined] + deactivate_modules_bool = protocol.params.deactivate_modules # type: ignore[attr-defined] + helpers.comment_protocol_version(protocol, "01") + dry_run = False TIP_TRASH = ( False # True = Used tips go in Trash, False = Used tips go back into rack ) res_type = "nest_12_reservoir_15ml" - - num_samples = 8 - wash1_vol = 500.0 - wash2_vol = wash3_vol = 900.0 - lysis_vol = 200.0 + global m1000_tips + num_samples = 96 + wash1_vol = wash2_vol = wash3_vol = 400.0 + lysis_vol = 90.0 sample_vol = 10.0 # Sample should be pelleted tissue/bacteria/cells bind_vol = 600.0 bind2_vol = 500.0 elution_vol = 75.0 + def tipcheck(m1000: InstrumentContext) -> None: + """Tip tracking function.""" + global m1000_tips + if m1000_tips >= 3 * 96: + m1000.reset_tipracks() + m1000_tips == 0 + m1000.pick_up_tip() + m1000_tips += 8 + # Protocol Parameters deepwell_type = "nest_96_wellplate_2ml_deep" @@ -97,37 +110,41 @@ def run(ctx: protocol_api.ProtocolContext) -> None: bead_vol = 25.0 starting_vol = lysis_vol + sample_vol binding_buffer_vol = bind_vol + bead_vol - ctx.load_trash_bin("A3") - h_s: HeaterShakerContext = ctx.load_module(helpers.hs_str, "D1") # type: ignore[assignment] + protocol.load_trash_bin("A3") + h_s: HeaterShakerContext = protocol.load_module( + helpers.hs_str, "D1" + ) # type: ignore[assignment] labware_name = "Samples" sample_plate, h_s_adapter = helpers.load_hs_adapter_and_labware( deepwell_type, h_s, labware_name ) h_s.close_labware_latch() - temp: TemperatureModuleContext = ctx.load_module( + temp: TemperatureModuleContext = protocol.load_module( helpers.temp_str, "D3" ) # type: ignore[assignment] elutionplate, temp_adapter = helpers.load_temp_adapter_and_labware( "armadillo_96_wellplate_200ul_pcr_full_skirt", temp, "Elution Plate" ) - magblock: MagneticBlockContext = ctx.load_module( + magblock: MagneticBlockContext = protocol.load_module( helpers.mag_str, "C1" ) # type: ignore[assignment] - waste_reservoir = ctx.load_labware("nest_1_reservoir_195ml", "B3", "Liquid Waste") + waste_reservoir = protocol.load_labware( + "nest_1_reservoir_290ml", "B3", "Liquid Waste" + ) waste = waste_reservoir.wells()[0].top() - res1 = ctx.load_labware(res_type, "D2", "reagent reservoir 1") - res2 = ctx.load_labware(res_type, "C2", "reagent reservoir 2") + res1 = protocol.load_labware(res_type, "D2", "reagent reservoir 1") + res2 = protocol.load_labware(res_type, "C2", "reagent reservoir 2") + res3 = protocol.load_labware(res_type, "B2", "reagent reservoir 3") num_cols = math.ceil(num_samples / 8) # Load tips and combine all similar boxes - tips1000 = ctx.load_labware("opentrons_flex_96_tiprack_1000ul", "A1", "Tips 1") - tips1001 = ctx.load_labware("opentrons_flex_96_tiprack_1000ul", "A2", "Tips 2") - tips1002 = ctx.load_labware("opentrons_flex_96_tiprack_1000ul", "B1", "Tips 3") - tips = [*tips1000.wells()[num_samples:96], *tips1001.wells(), *tips1002.wells()] + tips1000 = protocol.load_labware("opentrons_flex_96_tiprack_1000ul", "A1", "Tips 1") + tips1001 = protocol.load_labware("opentrons_flex_96_tiprack_1000ul", "A2", "Tips 2") + tips1002 = protocol.load_labware("opentrons_flex_96_tiprack_1000ul", "B1", "Tips 3") tips_sn = tips1000.wells()[:num_samples] # load instruments - m1000 = ctx.load_instrument( + m1000 = protocol.load_instrument( "flex_8channel_1000", mount, tip_racks=[tips1000, tips1001, tips1002] ) @@ -135,50 +152,32 @@ def run(ctx: protocol_api.ProtocolContext) -> None: Here is where you can define the locations of your reagents. """ lysis_ = res1.wells()[0] - binding_buffer = res1.wells()[1:4] - bind2_res = res1.wells()[4:8] - wash1 = res1.wells()[6:8] - elution_solution = res1.wells()[-1] - wash2 = res2.wells()[:6] - wash3 = res2.wells()[6:] - + binding_buffer = res1.wells()[1:8] + bind2_res = res1.wells()[8:12] + all_washes = res2.wells()[1:] + elution_solution = res2.wells()[0] + all_washes.extend(res3.wells()[:2]) samples_m = sample_plate.rows()[0][:num_cols] elution_samples_m = elutionplate.rows()[0][:num_cols] # Redefine per well for liquid definitions samps = sample_plate.wells()[: (8 * num_cols)] - liquid_vols_and_wells: Dict[str, List[Dict[str, Well | List[Well] | float]]] = { "Lysis and PK": [{"well": lysis_, "volume": 12320.0}], "Beads and Binding": [{"well": binding_buffer, "volume": 11875.0}], "Binding 2": [{"well": bind2_res, "volume": 13500.0}], - "Final Elution": [{"well": elution_solution, "volume": 52000}], + "Final Elution": [{"well": elution_solution, "volume": 1200.0}], "Samples": [{"well": samps, "volume": 0.0}], - "Reagents": [{"well": res2.wells(), "volume": 9000.0}], + "Reagents": [{"well": all_washes, "volume": 9800.0}], } - flattened_list_of_wells = helpers.find_liquid_height_of_loaded_liquids( - ctx, liquid_vols_and_wells, m1000 - ) + helpers.find_liquid_height_of_loaded_liquids(protocol, liquid_vols_and_wells, m1000) m1000.flow_rate.aspirate = 300 m1000.flow_rate.dispense = 300 m1000.flow_rate.blow_out = 300 - def tiptrack(tipbox: List[Well]) -> None: - """Track Tips.""" - global tip1k - global drop_count - if tipbox == tips: - m1000.pick_up_tip(tipbox[int(tip1k)]) - tip1k = tip1k + 8 - - drop_count = drop_count + 8 - if drop_count >= 150: - drop_count = 0 - ctx.pause("Please empty the waste bin of all the tips before continuing.") - def remove_supernatant(vol: float) -> None: """Remove supernatant.""" - ctx.comment("-----Removing Supernatant-----") + protocol.comment("-----Removing Supernatant-----") m1000.flow_rate.aspirate = 30 num_trans = math.ceil(vol / 980) vol_per_trans = vol / num_trans @@ -198,7 +197,7 @@ def remove_supernatant(vol: float) -> None: m1000.flow_rate.aspirate = 300 # Transfer from Magdeck plate to H-S - helpers.move_labware_to_hs(ctx, sample_plate, h_s, h_s_adapter) + helpers.move_labware_to_hs(protocol, sample_plate, h_s, h_s_adapter) def bead_mixing( well: Well, pip: InstrumentContext, mvol: float, reps: int = 8 @@ -261,6 +260,7 @@ def mixing(well: Well, pip: InstrumentContext, mvol: float, reps: int = 8) -> No dispensing at the top and 2 cycles of aspirating from middle, dispensing at the bottom """ + pip.liquid_presence_detection = False center = well.top(5) asp = well.bottom(1) disp = well.top(-8) @@ -290,15 +290,18 @@ def mixing(well: Well, pip: InstrumentContext, mvol: float, reps: int = 8) -> No def lysis(vol: float, source: Well) -> None: """Lysis.""" - ctx.comment("-----Beginning Lysis Steps-----") - ctx.pause(msg="\n Hello \n - step 1 \n - step 2") + protocol.comment("-----Beginning Lysis Steps-----") num_transfers = math.ceil(vol / 980) - tiptrack(tips) + tipcheck(m1000) + total_lysis_aspirated = 0.0 for i in range(num_cols): src = source tvol = vol / num_transfers # Mix Shield and PK before transferring first time if i == 0: + m1000.liquid_presence_detection = ( + False # turn off liquid detection during mixing + ) for x in range(lysis_rep_1): m1000.aspirate(vol, src.bottom(1)) m1000.dispense(vol, src.bottom(8)) @@ -308,15 +311,14 @@ def lysis(vol: float, source: Well) -> None: m1000.aspirate(tvol, src.bottom(1)) m1000.air_gap(10) m1000.dispense(m1000.current_volume, samples_m[i].top()) - + total_lysis_aspirated += tvol * 8 # Mix shield and pk with samples for i in range(num_cols): if i != 0: - tiptrack(tips) + tipcheck(m1000) mixing(samples_m[i], m1000, tvol, reps=lysis_rep_2) m1000.drop_tip() if TIP_TRASH else m1000.return_tip() - - helpers.set_hs_speed(ctx, h_s, heater_shaker_speed, lysis_incubation, True) + helpers.set_hs_speed(protocol, h_s, heater_shaker_speed, lysis_incubation, True) def bind(vol1: float, vol2: float) -> None: """Binding. @@ -334,9 +336,9 @@ def bind(vol1: float, vol2: float) -> None: supernatant to the final clean elutions PCR plate. """ - ctx.comment("-----Beginning Binding Steps-----") + protocol.comment("-----Beginning Binding Steps-----") for i, well in enumerate(samples_m): - tiptrack(tips) + tipcheck(m1000) num_trans = math.ceil(vol1 / 980) vol_per_trans = vol1 / num_trans source = binding_buffer[i // 2] @@ -360,15 +362,19 @@ def bind(vol1: float, vol2: float) -> None: m1000.air_gap(10) m1000.drop_tip() if TIP_TRASH else m1000.return_tip() - helpers.set_hs_speed(ctx, h_s, heater_shaker_speed * 0.9, bind_time_1, True) + helpers.set_hs_speed( + protocol, h_s, heater_shaker_speed * 0.9, bind_time_1, True + ) # Transfer from H-S plate to Magdeck plate - helpers.move_labware_from_hs_to_destination(ctx, sample_plate, h_s, magblock) + helpers.move_labware_from_hs_to_destination( + protocol, sample_plate, h_s, magblock + ) for bindi in np.arange( settling_time + 1, 0, -0.5 ): # Settling time delay with countdown timer - ctx.delay( + protocol.delay( minutes=0.5, msg="There are " + str(bindi) + " minutes left in the incubation.", ) @@ -376,8 +382,8 @@ def bind(vol1: float, vol2: float) -> None: # remove initial supernatant remove_supernatant(vol1 + starting_vol) - ctx.comment("-----Beginning Bind #2 Steps-----") - tiptrack(tips) + protocol.comment("-----Beginning Bind #2 Steps-----") + tipcheck(m1000) for i, well in enumerate(samples_m): num_trans = math.ceil(vol2 / 980) vol_per_trans = vol2 / num_trans @@ -402,20 +408,22 @@ def bind(vol1: float, vol2: float) -> None: for i in range(num_cols): if i != 0: - tiptrack(tips) + tipcheck(m1000) bead_mixing( samples_m[i], m1000, vol_per_trans, reps=3 if not dry_run else 1 ) m1000.drop_tip() if TIP_TRASH else m1000.return_tip() - helpers.set_hs_speed(ctx, h_s, heater_shaker_speed, bind_time_2, True) + helpers.set_hs_speed(protocol, h_s, heater_shaker_speed, bind_time_2, True) # Transfer from H-S plate to Magdeck plate - helpers.move_labware_from_hs_to_destination(ctx, sample_plate, h_s, magblock) + helpers.move_labware_from_hs_to_destination( + protocol, sample_plate, h_s, magblock + ) for bindi in np.arange( settling_time + 1, 0, -0.5 ): # Settling time delay with countdown timer - ctx.delay( + protocol.delay( minutes=0.5, msg="There are " + str(bindi) + " minutes left in the incubation.", ) @@ -426,52 +434,43 @@ def bind(vol1: float, vol2: float) -> None: def wash(vol: float, source: List[Well]) -> None: """Wash Steps.""" global whichwash # Defines which wash the protocol is on to log on the app - - if source == wash1: - whichwash = 1 - const = 6 // len(source) - if source == wash2: - whichwash = 2 - const = 6 // len(source) - height = 1 - if source == wash3: - whichwash = 3 - const = 6 // len(source) - height = 1 - - ctx.comment("-----Wash #" + str(whichwash) + " is starting now------") + protocol.comment("-----Now starting Wash #" + str(whichwash) + "-----") + global wash_volume_tracker num_trans = math.ceil(vol / 980) vol_per_trans = vol / num_trans - tiptrack(tips) + tipcheck(m1000) for i, m in enumerate(samples_m): - if source == wash1: - if i == 0 or i == 3: - height = 10 - else: - height = 1 - src = source[i // const] + src = source[whichwash] for n in range(num_trans): if m1000.current_volume > 0: m1000.dispense(m1000.current_volume, src.top()) m1000.require_liquid_presence(src) m1000.transfer( vol_per_trans, - src.bottom(height), + src.bottom(dot_bottom), m.top(), air_gap=20, new_tip="never", ) + wash_volume_tracker += vol_per_trans * 8 + if wash_volume_tracker >= 9600: + whichwash += 1 + src = source[whichwash] + protocol.comment(f"new wash source {whichwash}") + wash_volume_tracker = 0.0 m1000.drop_tip() if TIP_TRASH else m1000.return_tip() - helpers.set_hs_speed(ctx, h_s, heater_shaker_speed * 0.9, wash_time, True) + helpers.set_hs_speed(protocol, h_s, heater_shaker_speed * 0.9, wash_time, True) - helpers.move_labware_from_hs_to_destination(ctx, sample_plate, h_s, magblock) + helpers.move_labware_from_hs_to_destination( + protocol, sample_plate, h_s, magblock + ) for washi in np.arange( settling_time, 0, -0.5 ): # settling time timer for washes - ctx.delay( + protocol.delay( minutes=0.5, msg="There are " + str(washi) @@ -483,27 +482,31 @@ def wash(vol: float, source: List[Well]) -> None: remove_supernatant(vol) def elute(vol: float) -> None: - tiptrack(tips) + tipcheck(m1000) + total_elution_vol = 0.0 for i, m in enumerate(samples_m): m1000.require_liquid_presence(elution_solution) m1000.aspirate(vol, elution_solution) m1000.air_gap(20) m1000.dispense(m1000.current_volume, m.top(-3)) + total_elution_vol += vol m1000.drop_tip() if TIP_TRASH else m1000.return_tip() - helpers.set_hs_speed(ctx, h_s, heater_shaker_speed * 0.9, wash_time, True) + helpers.set_hs_speed(protocol, h_s, heater_shaker_speed * 0.9, wash_time, True) # Transfer back to magnet - helpers.move_labware_from_hs_to_destination(ctx, sample_plate, h_s, magblock) + helpers.move_labware_from_hs_to_destination( + protocol, sample_plate, h_s, magblock + ) for elutei in np.arange(settling_time, 0, -0.5): - ctx.delay( + protocol.delay( minutes=0.5, msg="Incubating on MagDeck for " + str(elutei) + " more minutes.", ) for i, (m, e) in enumerate(zip(samples_m, elution_samples_m)): - tiptrack(tips) + tipcheck(m1000) m1000.flow_rate.dispense = 100 m1000.flow_rate.aspirate = 25 m1000.transfer( @@ -521,16 +524,23 @@ def elute(vol: float) -> None: """ lysis(lysis_vol, lysis_) bind(binding_buffer_vol, bind2_vol) - wash(wash1_vol, wash1) - wash(wash2_vol, wash2) - wash(wash3_vol, wash3) + wash(wash1_vol, all_washes) + wash(wash2_vol, all_washes) + wash(wash3_vol, all_washes) h_s.set_and_wait_for_temperature(55) for beaddry in np.arange(drybeads, 0, -0.5): - ctx.delay( + protocol.delay( minutes=0.5, msg="There are " + str(beaddry) + " minutes left in the drying step.", ) elute(elution_vol) h_s.deactivate_heater() - flattened_list_of_wells.extend([waste_reservoir["A1"], elutionplate["A1"]]) - helpers.find_liquid_height_of_all_wells(ctx, m1000, flattened_list_of_wells) + helpers.clean_up_plates( + m1000, + [elutionplate, sample_plate, res1, res3, res2], + waste_reservoir["A1"], + 1000, + ) + helpers.find_liquid_height_of_all_wells(protocol, m1000, [waste_reservoir["A1"]]) + if deactivate_modules_bool: + helpers.deactivate_modules(protocol) diff --git a/abr-testing/abr_testing/protocols/active_protocols/11_Dynabeads_IP_Flex_96well_RIT.py b/abr-testing/abr_testing/protocols/active_protocols/11_Dynabeads_IP_Flex_96well_RIT.py index e885ec45a5e..44db654cc1f 100644 --- a/abr-testing/abr_testing/protocols/active_protocols/11_Dynabeads_IP_Flex_96well_RIT.py +++ b/abr-testing/abr_testing/protocols/active_protocols/11_Dynabeads_IP_Flex_96well_RIT.py @@ -1,5 +1,5 @@ """Immunoprecipitation by Dynabeads.""" -from opentrons.protocol_api import ProtocolContext, ParameterContext, Well +from opentrons.protocol_api import ProtocolContext, ParameterContext, Well, Labware from opentrons.protocol_api.module_contexts import ( HeaterShakerContext, TemperatureModuleContext, @@ -15,7 +15,7 @@ } requirements = { - "robotType": "OT-3", + "robotType": "Flex", "apiLevel": "2.21", } @@ -25,6 +25,7 @@ def add_parameters(parameters: ParameterContext) -> None: helpers.create_hs_speed_parameter(parameters) helpers.create_two_pipette_mount_parameters(parameters) helpers.create_dot_bottom_parameter(parameters) + helpers.create_deactivate_modules_parameter(parameters) NUM_COL = 12 @@ -34,7 +35,7 @@ def add_parameters(parameters: ParameterContext) -> None: BEADS_VOL = 50 AB_VOL = 50 SAMPLE_VOL = 200 -WASH_TIMES = 3 +WASH_TIMES = 6 WASH_VOL = 200 ELUTION_VOL = 50 @@ -48,64 +49,78 @@ def add_parameters(parameters: ParameterContext) -> None: TIP_TRASH = False -def run(ctx: ProtocolContext) -> None: +def run(protocol: ProtocolContext) -> None: """Protocol.""" # defining variables inside def run - heater_shaker_speed = ctx.params.heater_shaker_speed # type: ignore[attr-defined] - ASP_HEIGHT = ctx.params.dot_bottom # type: ignore[attr-defined] - single_channel_mount = ctx.params.pipette_mount_1 # type: ignore[attr-defined] - eight_channel_mount = ctx.params.pipette_mount_2 # type: ignore[attr-defined] + heater_shaker_speed = protocol.params.heater_shaker_speed # type: ignore[attr-defined] + ASP_HEIGHT = protocol.params.dot_bottom # type: ignore[attr-defined] + single_channel_mount = protocol.params.pipette_mount_1 # type: ignore[attr-defined] + eight_channel_mount = protocol.params.pipette_mount_2 # type: ignore[attr-defined] + deactivate_modules_bool = protocol.params.deactivate_modules # type: ignore[attr-defined] + helpers.comment_protocol_version(protocol, "01") + MIX_SPEED = heater_shaker_speed MIX_SEC = 10 # if on deck: - INCUBATION_SPEEND = heater_shaker_speed * 0.5 + INCUBATION_SPEED = heater_shaker_speed * 0.5 INCUBATION_MIN = 60 # load labware - sample_plate = ctx.load_labware("nest_96_wellplate_2ml_deep", "B2", "samples") - wash_res = ctx.load_labware("nest_12_reservoir_15ml", "B1", "wash") - reagent_res = ctx.load_labware( + sample_plate_1 = protocol.load_labware( + "nest_96_wellplate_2ml_deep", "B2", "sample plate 1" + ) + sample_plate_2 = protocol.load_labware( + "nest_96_wellplate_2ml_deep", "C4", "sample plate 2" + ) + + wash_res = protocol.load_labware("nest_12_reservoir_15ml", "B1", "wash") + reagent_res = protocol.load_labware( "opentrons_15_tuberack_nest_15ml_conical", "C3", "reagents" ) - waste_res = ctx.load_labware("nest_1_reservoir_290ml", "D2", "waste") + waste_res = protocol.load_labware("nest_1_reservoir_290ml", "D2", "Liquid Waste") - tips = ctx.load_labware("opentrons_flex_96_tiprack_1000ul", "B3") - tips_sample = ctx.load_labware( + tips = protocol.load_labware("opentrons_flex_96_tiprack_1000ul", "B3") + tips_sample = protocol.load_labware( "opentrons_flex_96_tiprack_1000ul", "A2", "sample tips" ) tips_sample_loc = tips_sample.wells()[:95] if READY_FOR_SDSPAGE == 0: - tips_elu = ctx.load_labware( + tips_elu = protocol.load_labware( "opentrons_flex_96_tiprack_1000ul", "A1", "elution tips" ) tips_elu_loc = tips_elu.wells()[:95] - tips_reused = ctx.load_labware( + tips_reused = protocol.load_labware( "opentrons_flex_96_tiprack_1000ul", "C2", "reused tips" ) tips_reused_loc = tips_reused.wells()[:95] - p1000 = ctx.load_instrument( + p1000 = protocol.load_instrument( "flex_8channel_1000", eight_channel_mount, tip_racks=[tips] ) - p1000_single = ctx.load_instrument( + p1000_single = protocol.load_instrument( "flex_1channel_1000", single_channel_mount, tip_racks=[tips] ) - h_s: HeaterShakerContext = ctx.load_module(helpers.hs_str, "D1") # type: ignore[assignment] + h_s: HeaterShakerContext = protocol.load_module( + helpers.hs_str, "D1" + ) # type: ignore[assignment] working_plate, h_s_adapter = helpers.load_hs_adapter_and_labware( "nest_96_wellplate_2ml_deep", h_s, "Working Plate" ) if READY_FOR_SDSPAGE == 0: - temp: TemperatureModuleContext = ctx.load_module( + temp: TemperatureModuleContext = protocol.load_module( helpers.temp_str, "D3" ) # type: ignore[assignment] final_plate, temp_adapter = helpers.load_temp_adapter_and_labware( "nest_96_wellplate_2ml_deep", temp, "Final Plate" ) - mag: MagneticBlockContext = ctx.load_module(helpers.mag_str, "C1") # type: ignore[assignment] + mag: MagneticBlockContext = protocol.load_module( + helpers.mag_str, "C1" + ) # type: ignore[assignment] # liquids - samples = sample_plate.rows()[0][:NUM_COL] # 1 + samples1 = sample_plate_1.rows()[0][:NUM_COL] # 1 + samples2 = sample_plate_2.rows()[0][:NUM_COL] # 1 beads = reagent_res.wells()[0] # 2 ab = reagent_res.wells()[1] # 3 elu = reagent_res.wells()[2] # 4 @@ -119,14 +134,15 @@ def run(ctx: ProtocolContext) -> None: liquid_vols_and_wells: Dict[ str, List[Dict[str, Union[Well, List[Well], float]]] ] = { - "Beads": [{"well": beads, "volume": 4900.0}], - "AB": [{"well": ab, "volume": 4900.0}], - "Elution": [{"well": elu, "volume": 4900.0}], - "Wash": [{"well": wash, "volume": 750.0}], - "Samples": [{"well": samples, "volume": 250.0}], + "Beads": [{"well": beads, "volume": 9800.0}], + "AB": [{"well": ab, "volume": 9800.0}], + "Elution": [{"well": elu, "volume": 9800.0}], + "Wash": [{"well": wash, "volume": 1500.0}], + "Samples 1": [{"well": samples1, "volume": 250.0}], + "Samples 2": [{"well": samples2, "volume": 250.0}], } helpers.find_liquid_height_of_loaded_liquids( - ctx, liquid_vols_and_wells, p1000_single + protocol, liquid_vols_and_wells, p1000_single ) def transfer_plate_to_plate( @@ -193,9 +209,6 @@ def discard(vol3: float, start: List[Well]) -> None: """Discard function.""" global waste_vol global waste_vol_chk - if waste_vol_chk >= WASTE_VOL_MAX: - ctx.pause("Empty Liquid Waste") - waste_vol_chk = 0 waste_vol = 0.0 for k in range(NUM_COL): p1000.pick_up_tip(tips_reused_loc[k * 8]) @@ -210,64 +223,77 @@ def discard(vol3: float, start: List[Well]) -> None: waste_vol_chk = waste_vol_chk + waste_vol # protocol - - # Add beads, samples and antibody solution - h_s.close_labware_latch() - transfer_well_to_plate(BEADS_VOL, beads, working_wells, 2) - - helpers.move_labware_from_hs_to_destination(ctx, working_plate, h_s, mag) - - ctx.delay(minutes=MAG_DELAY_MIN) - discard(BEADS_VOL * 1.1, working_cols) - - helpers.move_labware_to_hs(ctx, working_plate, h_s, h_s_adapter) - - transfer_plate_to_plate(SAMPLE_VOL, samples, working_cols, 1) - transfer_well_to_plate(AB_VOL, ab, working_wells, 3) - - h_s.set_and_wait_for_shake_speed(rpm=MIX_SPEED) - ctx.delay(seconds=MIX_SEC) - - h_s.set_and_wait_for_shake_speed(rpm=INCUBATION_SPEEND) - ctx.delay(seconds=INCUBATION_MIN * 60) - h_s.deactivate_shaker() - - helpers.move_labware_from_hs_to_destination(ctx, working_plate, h_s, mag) - - ctx.delay(minutes=MAG_DELAY_MIN) - vol_total = SAMPLE_VOL + AB_VOL - discard(vol_total * 1.1, working_cols) - - # Wash - for _ in range(WASH_TIMES): - helpers.move_labware_to_hs(ctx, working_plate, h_s, h_s_adapter) - - transfer_well_to_plate(WASH_VOL, wash, working_cols, 5) - helpers.set_hs_speed(ctx, h_s, MIX_SPEED, MIX_SEC / 60, True) - helpers.move_labware_from_hs_to_destination(ctx, working_plate, h_s, mag) - ctx.delay(minutes=MAG_DELAY_MIN) - discard(WASH_VOL * 1.1, working_cols) - - # Elution - helpers.move_labware_to_hs(ctx, working_plate, h_s, h_s_adapter) - - transfer_well_to_plate(ELUTION_VOL, elu, working_wells, 4) - if READY_FOR_SDSPAGE == 1: - ctx.pause("Seal the Working Plate") - h_s.set_and_wait_for_temperature(70) - helpers.set_hs_speed(ctx, h_s, MIX_SPEED, (MIX_SEC / 60) + 10, True) - h_s.deactivate_heater() - h_s.open_labware_latch() - ctx.pause("Protocol Complete") - - elif READY_FOR_SDSPAGE == 0: - helpers.set_hs_speed(ctx, h_s, MIX_SPEED, (MIX_SEC / 60) + 2, True) - - temp.set_temperature(4) - helpers.move_labware_from_hs_to_destination(ctx, working_plate, h_s, mag) - ctx.delay(minutes=MAG_DELAY_MIN) - transfer_plate_to_plate(ELUTION_VOL * 1.1, working_cols, final_cols, 6) - temp.deactivate() - end_wells_to_probe = [reagent_res["A1"], reagent_res["B1"], reagent_res["C1"]] - end_wells_to_probe.extend(wash_res.wells()) - helpers.find_liquid_height_of_all_wells(ctx, p1000_single, end_wells_to_probe) + def run(sample_plate: Labware) -> None: + """Protocol.""" + # Add beads, samples and antibody solution + samples = sample_plate.rows()[0][:NUM_COL] # 1 + h_s.close_labware_latch() + transfer_well_to_plate(BEADS_VOL, beads, working_wells, 2) + + helpers.move_labware_from_hs_to_destination(protocol, working_plate, h_s, mag) + + protocol.delay(minutes=MAG_DELAY_MIN) + discard(BEADS_VOL * 1.1, working_cols) + + helpers.move_labware_to_hs(protocol, working_plate, h_s, h_s_adapter) + + transfer_plate_to_plate(SAMPLE_VOL, samples, working_cols, 1) + transfer_well_to_plate(AB_VOL, ab, working_wells, 3) + + h_s.set_and_wait_for_shake_speed(rpm=MIX_SPEED) + protocol.delay(seconds=MIX_SEC) + + h_s.set_and_wait_for_shake_speed(rpm=INCUBATION_SPEED) + protocol.delay(seconds=INCUBATION_MIN * 60) + h_s.deactivate_shaker() + + helpers.move_labware_from_hs_to_destination(protocol, working_plate, h_s, mag) + + protocol.delay(minutes=MAG_DELAY_MIN) + vol_total = SAMPLE_VOL + AB_VOL + discard(vol_total * 1.1, working_cols) + + # Wash + for _ in range(WASH_TIMES): + helpers.move_labware_to_hs(protocol, working_plate, h_s, h_s_adapter) + + transfer_well_to_plate(WASH_VOL, wash, working_cols, 5) + helpers.set_hs_speed(protocol, h_s, MIX_SPEED, MIX_SEC / 60, True) + helpers.move_labware_from_hs_to_destination( + protocol, working_plate, h_s, mag + ) + protocol.delay(minutes=MAG_DELAY_MIN) + discard(WASH_VOL * 1.1, working_cols) + # Elution + helpers.move_labware_to_hs(protocol, working_plate, h_s, h_s_adapter) + transfer_well_to_plate(ELUTION_VOL, elu, working_wells, 4) + if READY_FOR_SDSPAGE == 1: + protocol.pause("Seal the Working Plate") + h_s.set_and_wait_for_temperature(70) + helpers.set_hs_speed(protocol, h_s, MIX_SPEED, (MIX_SEC / 60) + 10, True) + h_s.deactivate_heater() + h_s.open_labware_latch() + protocol.pause("Protocol Complete") + elif READY_FOR_SDSPAGE == 0: + helpers.set_hs_speed(protocol, h_s, MIX_SPEED, (MIX_SEC / 60) + 2, True) + + temp.set_temperature(4) + helpers.move_labware_from_hs_to_destination( + protocol, working_plate, h_s, mag + ) + protocol.delay(minutes=MAG_DELAY_MIN) + transfer_plate_to_plate(ELUTION_VOL * 1.1, working_cols, final_cols, 6) + temp.deactivate() + helpers.clean_up_plates(p1000_single, [sample_plate], waste, 1000) + helpers.move_labware_to_hs(protocol, working_plate, h_s, h_s_adapter) + + run(sample_plate_1) + # swap plates + protocol.move_labware(sample_plate_1, "B4", True) + protocol.move_labware(sample_plate_2, "B2", True) + run(sample_plate_2) + + helpers.clean_up_plates(p1000_single, [wash_res], waste, 1000) + helpers.find_liquid_height_of_all_wells(protocol, p1000_single, [waste_res["A1"]]) + if deactivate_modules_bool: + helpers.deactivate_modules(protocol) 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 75658f11438..ff38e8cf7c7 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 @@ -18,7 +18,7 @@ metadata = { "protocolName": "KAPA HyperPlus Library Preparation", - "author": "Your Name ", + "author": "Tony Ngumah ", } requirements = {"robotType": "Flex", "apiLevel": "2.21"} @@ -41,6 +41,7 @@ def add_parameters(parameters: ParameterContext) -> None: helpers.create_disposable_lid_parameter(parameters) helpers.create_tc_lid_deck_riser_parameter(parameters) helpers.create_two_pipette_mount_parameters(parameters) + helpers.create_deactivate_modules_parameter(parameters) parameters.add_int( variable_name="num_samples", display_name="number of samples", @@ -68,22 +69,25 @@ def add_parameters(parameters: ParameterContext) -> None: ) -def run(ctx: ProtocolContext) -> None: +def run(protocol: ProtocolContext) -> None: """Protocol.""" USE_GRIPPER = True - trash_tips = ctx.params.trash_tips # type: ignore[attr-defined] - 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] + deactivate_mods = protocol.params.deactivate_modules # type: ignore[attr-defined] + trash_tips = protocol.params.trash_tips # type: ignore[attr-defined] + dry_run = protocol.params.dry_run # type: ignore[attr-defined] + pipette_1000_mount = protocol.params.pipette_mount_1 # type: ignore[attr-defined] + pipette_50_mount = protocol.params.pipette_mount_2 # type: ignore[attr-defined] + deck_riser = protocol.params.deck_riser # type: ignore[attr-defined] + helpers.comment_protocol_version(protocol, "01") + REUSE_ETOH_TIPS = True REUSE_RSB_TIPS = ( True # Reuse tips for RSB buffer (adding RSB, mixing, and transferring) ) REUSE_REMOVE_TIPS = True # Reuse tips for supernatant removal - num_samples = ctx.params.num_samples # type: ignore[attr-defined] - PCRCYCLES = ctx.params.PCR_CYCLES # type: ignore[attr-defined] - disposable_lid = ctx.params.disposable_lid # type: ignore[attr-defined] + num_samples = protocol.params.num_samples # type: ignore[attr-defined] + PCRCYCLES = protocol.params.PCR_CYCLES # type: ignore[attr-defined] + disposable_lid = protocol.params.disposable_lid # type: ignore[attr-defined] Fragmentation_time = 10 ligation_tc_time = 15 used_lids: List[Labware] = [] @@ -111,10 +115,10 @@ def run(ctx: ProtocolContext) -> None: # etoh_vol = 400.0 # Importing Labware, Modules and Instruments - magblock: MagneticBlockContext = ctx.load_module( + magblock: MagneticBlockContext = protocol.load_module( helpers.mag_str, "D2" ) # type: ignore[assignment] - temp_mod: TemperatureModuleContext = ctx.load_module( + temp_mod: TemperatureModuleContext = protocol.load_module( helpers.temp_str, "B3" ) # type: ignore[assignment] temp_plate, temp_adapter = helpers.load_temp_adapter_and_labware( @@ -125,7 +129,7 @@ def run(ctx: ProtocolContext) -> None: if not dry_run: temp_mod.set_temperature(4) - tc_mod: ThermocyclerContext = ctx.load_module(helpers.tc_str) # type: ignore[assignment] + tc_mod: ThermocyclerContext = protocol.load_module(helpers.tc_str) # type: ignore[assignment] # Just in case tc_mod.open_lid() @@ -134,32 +138,32 @@ def run(ctx: ProtocolContext) -> None: ) samples_flp = FLP_plate.rows()[0][:num_cols] - sample_plate = ctx.load_labware( + sample_plate = protocol.load_labware( "armadillo_96_wellplate_200ul_pcr_full_skirt", "D1", "Sample Plate 1" ) - sample_plate_2 = ctx.load_labware( + sample_plate_2 = protocol.load_labware( "armadillo_96_wellplate_200ul_pcr_full_skirt", "B2", "Sample Plate 2" ) samples_2 = sample_plate_2.rows()[0][:num_cols] samples = sample_plate.rows()[0][:num_cols] - reservoir = ctx.load_labware( + reservoir = protocol.load_labware( "nest_96_wellplate_2ml_deep", "C2", "Beads + Buffer + Ethanol" ) # Load tipracks - tiprack_50_1 = ctx.load_labware("opentrons_flex_96_tiprack_50ul", "A3") - tiprack_50_2 = ctx.load_labware("opentrons_flex_96_tiprack_50ul", "A2") + tiprack_50_1 = protocol.load_labware("opentrons_flex_96_tiprack_50ul", "A3") + tiprack_50_2 = protocol.load_labware("opentrons_flex_96_tiprack_50ul", "A2") - tiprack_200_1 = ctx.load_labware("opentrons_flex_96_tiprack_200ul", "C1") - tiprack_200_2 = ctx.load_labware("opentrons_flex_96_tiprack_200ul", "C3") + tiprack_200_1 = protocol.load_labware("opentrons_flex_96_tiprack_200ul", "C1") + tiprack_200_2 = protocol.load_labware("opentrons_flex_96_tiprack_200ul", "C3") if trash_tips: - ctx.load_waste_chute() + protocol.load_waste_chute() unused_lids: List[Labware] = [] # Load TC Lids if disposable_lid: - unused_lids = helpers.load_disposable_lids(ctx, 5, ["C4"], deck_riser) + unused_lids = helpers.load_disposable_lids(protocol, 5, ["C4"], deck_riser) # Import Global Variables global tip50 @@ -168,12 +172,12 @@ def run(ctx: ProtocolContext) -> None: global p200_rack_count tip_count = {1000: 0, 50: 0} - p200 = ctx.load_instrument( + p200 = protocol.load_instrument( "flex_8channel_1000", pipette_1000_mount, tip_racks=[tiprack_200_1, tiprack_200_2], ) - p50 = ctx.load_instrument( + p50 = protocol.load_instrument( "flex_8channel_50", pipette_50_mount, tip_racks=[tiprack_50_1, tiprack_50_2] ) @@ -224,7 +228,7 @@ def run(ctx: ProtocolContext) -> None: waste2 = reservoir.columns()[7] waste2_res = waste2[0] - helpers.find_liquid_height_of_loaded_liquids(ctx, liquid_vols_and_wells, p50) + helpers.find_liquid_height_of_loaded_liquids(protocol, liquid_vols_and_wells, p50) def tip_track(pipette: InstrumentContext, tip_count: Dict) -> None: """Track tip usage.""" @@ -248,19 +252,19 @@ def run_tag_profile( ) -> Tuple[List[Labware], List[Labware]]: """Run Tag Profile.""" # Presetting Thermocycler Temps - ctx.comment( + protocol.comment( "****Starting Fragmentation Profile (37C for 10 minutes with 100C lid)****" ) tc_mod.set_lid_temperature(100) tc_mod.set_block_temperature(37) # Move Plate to TC - ctx.comment("****Moving Plate to Pre-Warmed TC Module Block****") - ctx.move_labware(sample_plate, tc_mod, use_gripper=USE_GRIPPER) + protocol.comment("****Moving Plate to Pre-Warmed TC Module Block****") + protocol.move_labware(sample_plate, tc_mod, use_gripper=USE_GRIPPER) if disposable_lid: lid_on_plate, unused_lids, used_lids = helpers.use_disposable_lid_with_tc( - ctx, unused_lids, used_lids, sample_plate, tc_mod + protocol, unused_lids, used_lids, sample_plate, tc_mod ) else: tc_mod.close_lid() @@ -271,13 +275,13 @@ def run_tag_profile( if disposable_lid: if len(used_lids) <= 1: - ctx.move_labware(lid_on_plate, "D4", use_gripper=True) + protocol.move_labware(lid_on_plate, "D4", use_gripper=True) else: - ctx.move_labware(lid_on_plate, used_lids[-2], use_gripper=True) + protocol.move_labware(lid_on_plate, used_lids[-2], use_gripper=True) # #Move Plate to H-S - ctx.comment("****Moving Plate off of TC****") + protocol.comment("****Moving Plate off of TC****") - ctx.move_labware(sample_plate, "D1", use_gripper=USE_GRIPPER) + protocol.move_labware(sample_plate, "D1", use_gripper=USE_GRIPPER) return unused_lids, used_lids def run_er_profile( @@ -285,19 +289,19 @@ def run_er_profile( ) -> Tuple[List[Labware], List[Labware]]: """End Repair Profile.""" # Presetting Thermocycler Temps - ctx.comment( + protocol.comment( "****Starting End Repair Profile (65C for 30 minutes with 100C lid)****" ) tc_mod.set_lid_temperature(100) tc_mod.set_block_temperature(65) # Move Plate to TC - ctx.comment("****Moving Plate to Pre-Warmed TC Module Block****") - ctx.move_labware(sample_plate, tc_mod, use_gripper=USE_GRIPPER) + protocol.comment("****Moving Plate to Pre-Warmed TC Module Block****") + protocol.move_labware(sample_plate, tc_mod, use_gripper=USE_GRIPPER) if disposable_lid: lid_on_plate, unused_lids, used_lids = helpers.use_disposable_lid_with_tc( - ctx, unused_lids, used_lids, sample_plate, tc_mod + protocol, unused_lids, used_lids, sample_plate, tc_mod ) else: tc_mod.close_lid() @@ -311,13 +315,13 @@ def run_er_profile( if disposable_lid: # move lid if len(used_lids) <= 1: - ctx.move_labware(lid_on_plate, "C4", use_gripper=True) + protocol.move_labware(lid_on_plate, "C4", use_gripper=True) else: - ctx.move_labware(lid_on_plate, used_lids[-2], use_gripper=True) + protocol.move_labware(lid_on_plate, used_lids[-2], use_gripper=True) # #Move Plate to H-S - ctx.comment("****Moving Plate off of TC****") + protocol.comment("****Moving Plate off of TC****") - ctx.move_labware(sample_plate, "D1", use_gripper=USE_GRIPPER) + protocol.move_labware(sample_plate, "D1", use_gripper=USE_GRIPPER) return unused_lids, used_lids def run_ligation_profile( @@ -325,20 +329,20 @@ def run_ligation_profile( ) -> Tuple[List[Labware], List[Labware]]: """Run Ligation Profile.""" # Presetting Thermocycler Temps - ctx.comment( + protocol.comment( "****Starting Ligation Profile (20C for 15 minutes with 100C lid)****" ) tc_mod.set_lid_temperature(100) tc_mod.set_block_temperature(20) # Move Plate to TC - ctx.comment("****Moving Plate to Pre-Warmed TC Module Block****") + protocol.comment("****Moving Plate to Pre-Warmed TC Module Block****") - ctx.move_labware(sample_plate, tc_mod, use_gripper=USE_GRIPPER) + protocol.move_labware(sample_plate, tc_mod, use_gripper=USE_GRIPPER) if disposable_lid: lid_on_plate, unused_lids, used_lids = helpers.use_disposable_lid_with_tc( - ctx, unused_lids, used_lids, sample_plate, tc_mod + protocol, unused_lids, used_lids, sample_plate, tc_mod ) else: tc_mod.close_lid() @@ -353,14 +357,14 @@ def run_ligation_profile( tc_mod.open_lid() if disposable_lid: if len(used_lids) <= 1: - ctx.move_labware(lid_on_plate, "C4", use_gripper=True) + protocol.move_labware(lid_on_plate, "C4", use_gripper=True) else: - ctx.move_labware(lid_on_plate, used_lids[-2], use_gripper=True) + protocol.move_labware(lid_on_plate, used_lids[-2], use_gripper=True) # #Move Plate to H-S - ctx.comment("****Moving Plate off of TC****") + protocol.comment("****Moving Plate off of TC****") - ctx.move_labware(sample_plate, "D1", use_gripper=USE_GRIPPER) + protocol.move_labware(sample_plate, "D1", use_gripper=USE_GRIPPER) return unused_lids, used_lids def run_amplification_profile( @@ -368,27 +372,27 @@ def run_amplification_profile( ) -> Tuple[List[Labware], List[Labware]]: """Run Amplification Profile.""" # Presetting Thermocycler Temps - ctx.comment( + protocol.comment( "Amplification Profile (37C for 5 min, 50C for 5 min with 100C lid)" ) tc_mod.set_lid_temperature(100) tc_mod.set_block_temperature(98) # Move Plate to TC - ctx.comment("****Moving Sample Plate onto TC****") - ctx.move_labware(sample_plate_2, tc_mod, use_gripper=USE_GRIPPER) + protocol.comment("****Moving Sample Plate onto TC****") + protocol.move_labware(sample_plate_2, tc_mod, use_gripper=USE_GRIPPER) if not dry_run: tc_mod.set_lid_temperature(105) if disposable_lid: lid_on_plate, unused_lids, used_lids = helpers.use_disposable_lid_with_tc( - ctx, unused_lids, used_lids, sample_plate_2, tc_mod + protocol, unused_lids, used_lids, sample_plate_2, tc_mod ) else: tc_mod.close_lid() if not dry_run: helpers.perform_pcr( - ctx, + protocol, tc_mod, initial_denature_time_sec=45, denaturation_time_sec=15, @@ -401,16 +405,16 @@ def run_amplification_profile( tc_mod.open_lid() if disposable_lid: if len(used_lids) <= 1: - ctx.move_labware(lid_on_plate, "C4", use_gripper=True) + protocol.move_labware(lid_on_plate, "C4", use_gripper=True) else: - ctx.move_labware(lid_on_plate, used_lids[-2], use_gripper=True) + protocol.move_labware(lid_on_plate, used_lids[-2], use_gripper=True) # Move Sample Plate to H-S - ctx.comment("****Moving Sample Plate back to H-S****") - ctx.move_labware(sample_plate_2, "D1", use_gripper=USE_GRIPPER) + protocol.comment("****Moving Sample Plate back to H-S****") + protocol.move_labware(sample_plate_2, "D1", use_gripper=USE_GRIPPER) # get FLP plate out of the way - ctx.comment("****Moving FLP Plate back to TC****") - ctx.move_labware(FLP_plate, tc_mod, use_gripper=USE_GRIPPER) + protocol.comment("****Moving FLP Plate back to TC****") + protocol.move_labware(FLP_plate, tc_mod, use_gripper=USE_GRIPPER) return unused_lids, used_lids def mix_beads( @@ -463,39 +467,39 @@ def mix_beads( def remove_supernatant(well: Well, vol: float, waste_: Well, column: int) -> None: """Remove supernatant.""" - ctx.comment("-------Removing " + str(vol) + "ul of Supernatant-------") + protocol.comment("-------Removing " + str(vol) + "ul of Supernatant-------") p200.flow_rate.aspirate = 15 num_trans = math.ceil(vol / 190) vol_per_trans = vol / num_trans tip_track(p200, tip_count) for x in range(num_trans): p200.aspirate(vol_per_trans / 2, well.bottom(0.2)) - ctx.delay(seconds=1) + protocol.delay(seconds=1) p200.aspirate(vol_per_trans / 2, well.bottom(0.2)) p200.air_gap(10) p200.dispense(p200.current_volume, waste_) p200.air_gap(10) if REUSE_REMOVE_TIPS: p200.return_tip() - ctx.comment("****Dropping Tip Back in Tip Box****") + protocol.comment("****Dropping Tip Back in Tip Box****") else: if trash_tips: p200.drop_tip() - ctx.comment("****Dropping Tip in Waste shoot****") + protocol.comment("****Dropping Tip in Waste shoot****") else: p200.return_tip() - ctx.comment("****Dropping Tip Back in Tip Box****") + protocol.comment("****Dropping Tip Back in Tip Box****") p200.flow_rate.aspirate = 150 def Fragmentation( unused_lids: List[Labware], used_lids: List[Labware] ) -> Tuple[List[Labware], List[Labware]]: """Fragmentation Function.""" - ctx.comment("-------Starting Fragmentation-------") + protocol.comment("-------Starting Fragmentation-------") for i in range(num_cols): - ctx.comment("Mixing and Transfering beads to column " + str(i + 1)) + protocol.comment("Mixing and Transfering beads to column " + str(i + 1)) p50.flow_rate.dispense = 15 tip_track(p50, tip_count) @@ -512,10 +516,10 @@ def Fragmentation( p50.flow_rate.dispense = 150 if trash_tips: p50.drop_tip() - ctx.comment("****Dropping Tip in Waste shoot****") + protocol.comment("****Dropping Tip in Waste shoot****") else: p50.return_tip() - ctx.comment("****Dropping Tip Back in Tip Box****") + protocol.comment("****Dropping Tip Back in Tip Box****") unused_lids, used_lids = run_tag_profile( unused_lids, used_lids @@ -526,11 +530,11 @@ def end_repair( unused_lids: List[Labware], used_lids: List[Labware] ) -> Tuple[List[Labware], List[Labware]]: """End Repair Function.""" - ctx.comment("-------Starting end_repair-------") + protocol.comment("-------Starting end_repair-------") for i in range(num_cols): - ctx.comment( + protocol.comment( "**** Mixing and Transfering beads to column " + str(i + 1) + " ****" ) @@ -549,10 +553,10 @@ def end_repair( p50.flow_rate.dispense = 150 if trash_tips: p50.drop_tip() - ctx.comment("****Dropping Tip in Waste shoot****") + protocol.comment("****Dropping Tip in Waste shoot****") else: p50.return_tip() - ctx.comment("****Dropping Tip Back in Tip Box****") + protocol.comment("****Dropping Tip Back in Tip Box****") unused_lids, used_lids = run_er_profile( unused_lids, used_lids @@ -565,8 +569,8 @@ def index_ligation( unused_lids: List[Labware], used_lids: List[Labware] ) -> Tuple[List[Labware], List[Labware]]: """Index Ligation.""" - ctx.comment("-------Ligating Indexes-------") - ctx.comment("-------Adding and Mixing ELM-------") + protocol.comment("-------Ligating Indexes-------") + protocol.comment("-------Adding and Mixing ELM-------") for i in samples: tip_track(p50, tip_count) p50.aspirate(ligation_vol, ligation_res) @@ -581,13 +585,13 @@ def index_ligation( p50.flow_rate.dispense = 150 if trash_tips: p50.drop_tip() - ctx.comment("****Dropping Tip in Waste shoot****") + protocol.comment("****Dropping Tip in Waste shoot****") else: p50.return_tip() - ctx.comment("****Dropping Tip Back in Tip Box****") + protocol.comment("****Dropping Tip Back in Tip Box****") # Add and mix adapters - ctx.comment("-------Adding and Mixing Adapters-------") + protocol.comment("-------Adding and Mixing Adapters-------") for i_well, x_well in zip(samples, adapters): tip_track(p50, tip_count) p50.aspirate(adapter_vol, x_well) @@ -600,10 +604,10 @@ def index_ligation( p50.dispense(40, i_well.bottom(8)) if trash_tips: p50.drop_tip() - ctx.comment("****Dropping Tip in Waste shoot****") + protocol.comment("****Dropping Tip in Waste shoot****") else: p50.return_tip() - ctx.comment("****Dropping Tip Back in Tip Box****") + protocol.comment("****Dropping Tip Back in Tip Box****") p50.flow_rate.aspirate = 150 p50.flow_rate.dispense = 150 @@ -613,13 +617,13 @@ def index_ligation( def lib_cleanup() -> None: """Litigation Clean up.""" - ctx.comment("-------Starting Cleanup-------") - ctx.comment("-------Adding and Mixing Cleanup Beads-------") + protocol.comment("-------Starting Cleanup-------") + protocol.comment("-------Adding and Mixing Cleanup Beads-------") # Move FLP plate off magnetic module if it's there if FLP_plate.parent == magblock: - ctx.comment("****Moving FLP Plate off Magnetic Module****") - ctx.move_labware(FLP_plate, tc_mod, use_gripper=USE_GRIPPER) + protocol.comment("****Moving FLP Plate off Magnetic Module****") + protocol.move_labware(FLP_plate, tc_mod, use_gripper=USE_GRIPPER) for x, i in enumerate(samples): mix_beads(p200, bead_res, bead_vol_1, 7 if x == 0 else 2, x) @@ -636,22 +640,22 @@ def lib_cleanup() -> None: p200.flow_rate.dispense = 150 if trash_tips: p200.drop_tip() - ctx.comment("****Dropping Tip in Waste shoot****") + protocol.comment("****Dropping Tip in Waste shoot****") else: p200.return_tip() - ctx.comment("****Dropping Tip Back in Tip Box****") + protocol.comment("****Dropping Tip Back in Tip Box****") - ctx.delay( + protocol.delay( minutes=bead_inc, msg="Please wait " + str(bead_inc) + " minutes while samples incubate at RT.", ) - ctx.comment("****Moving Labware to Magnet for Pelleting****") - ctx.move_labware(sample_plate, magblock, use_gripper=USE_GRIPPER) + protocol.comment("****Moving Labware to Magnet for Pelleting****") + protocol.move_labware(sample_plate, magblock, use_gripper=USE_GRIPPER) - ctx.delay(minutes=4.5, msg="Time for Pelleting") + protocol.delay(minutes=4.5, msg="Time for Pelleting") for col, i in enumerate(samples): remove_supernatant(i, 130, waste1_res, col) @@ -661,7 +665,7 @@ def lib_cleanup() -> None: p200.flow_rate.aspirate = 75 p200.flow_rate.dispense = 75 for y in range(2 if not dry_run else 1): - ctx.comment(f"-------Wash # {y+1} with Ethanol-------") + protocol.comment(f"-------Wash # {y+1} with Ethanol-------") if y == 0: # First wash this_res = etoh1_res this_waste_res = waste1_res @@ -672,42 +676,42 @@ def lib_cleanup() -> None: p200.aspirate(150, this_res) p200.air_gap(10) p200.dispense(p200.current_volume, i.top()) - ctx.delay(seconds=1) + protocol.delay(seconds=1) p200.air_gap(10) if not REUSE_ETOH_TIPS: p200.drop_tip() if trash_tips else p200.return_tip() - ctx.delay(seconds=10) + protocol.delay(seconds=10) # Remove the ethanol wash for x, i in enumerate(samp_list): tip_track(p200, tip_count) p200.aspirate(155, i) p200.air_gap(10) p200.dispense(p200.current_volume, this_waste_res) - ctx.delay(seconds=1) + protocol.delay(seconds=1) p200.air_gap(10) if trash_tips: p200.drop_tip() - ctx.comment("****Dropping Tip in Waste shoot****") + protocol.comment("****Dropping Tip in Waste shoot****") else: p200.return_tip() - ctx.comment("****Dropping Tip Back in Tip Box****") + protocol.comment("****Dropping Tip Back in Tip Box****") p200.flow_rate.aspirate = 150 p200.flow_rate.dispense = 150 # Wash complete, move on to drying steps. - ctx.delay(minutes=2, msg="Allow 3 minutes for residual ethanol to dry") + protocol.delay(minutes=2, msg="Allow 3 minutes for residual ethanol to dry") # Return Plate to H-S from Magnet - ctx.comment("****Moving sample plate off of Magnet****") - ctx.move_labware(sample_plate, "D1", use_gripper=USE_GRIPPER) + protocol.comment("****Moving sample plate off of Magnet****") + protocol.move_labware(sample_plate, "D1", use_gripper=USE_GRIPPER) # Adding RSB and Mixing for col, i in enumerate(samp_list): - ctx.comment(f"****Adding RSB to Columns: {col+1}****") + protocol.comment(f"****Adding RSB to Columns: {col+1}****") tip_track(p50, tip_count) p50.aspirate(rsb_vol_1, rsb_res) p50.air_gap(5) @@ -723,23 +727,23 @@ def lib_cleanup() -> None: p50.air_gap(5) if REUSE_RSB_TIPS: p50.return_tip() - ctx.comment("****Dropping Tip Back in Tip Box****") + protocol.comment("****Dropping Tip Back in Tip Box****") else: if trash_tips: p50.drop_tip() - ctx.comment("****Dropping Tip in Waste shoot****") + protocol.comment("****Dropping Tip in Waste shoot****") else: p50.return_tip() - ctx.comment("****Dropping Tip Back in Tip Box****") + protocol.comment("****Dropping Tip Back in Tip Box****") - ctx.delay( + protocol.delay( minutes=3, msg="Allow 3 minutes for incubation and liquid aggregation." ) - ctx.comment("****Move Samples to Magnet for Pelleting****") - ctx.move_labware(sample_plate, magblock, use_gripper=USE_GRIPPER) + protocol.comment("****Move Samples to Magnet for Pelleting****") + protocol.move_labware(sample_plate, magblock, use_gripper=USE_GRIPPER) - ctx.delay(minutes=2, msg="Please allow 2 minutes for beads to pellet.") + protocol.delay(minutes=2, msg="Please allow 2 minutes for beads to pellet.") p200.flow_rate.aspirate = 10 for i_int, (s, e) in enumerate(zip(samp_list, samples_2)): @@ -750,31 +754,31 @@ def lib_cleanup() -> None: p50.air_gap(5) if trash_tips: p50.drop_tip() - ctx.comment("****Dropping Tip in Waste shoot****") + protocol.comment("****Dropping Tip in Waste shoot****") else: p50.return_tip() - ctx.comment("****Dropping Tip Back in Tip Box****") + protocol.comment("****Dropping Tip Back in Tip Box****") # move new sample plate to D1 or heatershaker - ctx.comment("****Moving sample plate off of Magnet****") - ctx.move_labware(sample_plate_2, "D1", use_gripper=USE_GRIPPER) + protocol.comment("****Moving sample plate off of Magnet****") + protocol.move_labware(sample_plate_2, "D1", use_gripper=USE_GRIPPER) # Keep Sample PLate 1 to B2 - ctx.comment("****Moving Sample_plate_1 Plate off magnet to B2****") - ctx.move_labware(sample_plate, "B2", use_gripper=USE_GRIPPER) + protocol.comment("****Moving Sample_plate_1 Plate off magnet to B2****") + protocol.move_labware(sample_plate, "B2", use_gripper=USE_GRIPPER) - ctx.comment("****Moving FLP Plate off TC****") - ctx.move_labware(FLP_plate, magblock, use_gripper=USE_GRIPPER) + protocol.comment("****Moving FLP Plate off TC****") + protocol.move_labware(FLP_plate, magblock, use_gripper=USE_GRIPPER) def lib_amplification( unused_lids: List[Labware], used_lids: List[Labware] ) -> Tuple[List[Labware], List[Labware]]: """Library Amplification.""" - ctx.comment("-------Starting lib_amplification-------") + protocol.comment("-------Starting lib_amplification-------") for i in range(num_cols): - ctx.comment( + protocol.comment( "**** Mixing and Transfering beads to column " + str(i + 1) + " ****" ) mix_beads( @@ -795,10 +799,10 @@ def lib_amplification( p50.flow_rate.dispense = 150 if trash_tips: p50.drop_tip() - ctx.comment("****Dropping Tip in Waste shoot****") + protocol.comment("****Dropping Tip in Waste shoot****") else: p50.return_tip() - ctx.comment("****Dropping Tip Back in Tip Box****") + protocol.comment("****Dropping Tip Back in Tip Box****") unused_lids, used_lids = run_amplification_profile( unused_lids, used_lids @@ -807,8 +811,8 @@ def lib_amplification( def lib_cleanup_2() -> None: """Final Library Clean up.""" - ctx.comment("-------Starting Cleanup-------") - ctx.comment("-------Adding and Mixing Cleanup Beads-------") + protocol.comment("-------Starting Cleanup-------") + protocol.comment("-------Adding and Mixing Cleanup Beads-------") for x, i in enumerate(samples_2): mix_beads(p200, bead_res, bead_vol_2, 7 if x == 0 else 2, x) tip_track(p200, tip_count) @@ -826,22 +830,22 @@ def lib_cleanup_2() -> None: p200.flow_rate.dispense = 150 if trash_tips: p200.drop_tip() - ctx.comment("****Dropping Tip in Waste shoot****") + protocol.comment("****Dropping Tip in Waste shoot****") else: p200.return_tip() - ctx.comment("****Dropping Tip Back in Tip Box****") + protocol.comment("****Dropping Tip Back in Tip Box****") - ctx.delay( + protocol.delay( minutes=bead_inc, msg="Please wait " + str(bead_inc) + " minutes while samples incubate at RT.", ) - ctx.comment("****Moving Labware to Magnet for Pelleting****") - ctx.move_labware(sample_plate_2, magblock, use_gripper=USE_GRIPPER) + protocol.comment("****Moving Labware to Magnet for Pelleting****") + protocol.move_labware(sample_plate_2, magblock, use_gripper=USE_GRIPPER) - ctx.delay(minutes=4.5, msg="Time for Pelleting") + protocol.delay(minutes=4.5, msg="Time for Pelleting") for col, i in enumerate(samples_2): remove_supernatant(i, 130, waste1_res, col) @@ -851,7 +855,7 @@ def lib_cleanup_2() -> None: p200.flow_rate.aspirate = 75 p200.flow_rate.dispense = 75 for y in range(2 if not dry_run else 1): - ctx.comment(f"-------Wash # {y+1} with Ethanol-------") + protocol.comment(f"-------Wash # {y+1} with Ethanol-------") if y == 0: # First wash this_res = etoh1_res this_waste_res = waste1_res @@ -862,41 +866,41 @@ def lib_cleanup_2() -> None: p200.aspirate(150, this_res) p200.air_gap(10) p200.dispense(p200.current_volume, i.top()) - ctx.delay(seconds=1) + protocol.delay(seconds=1) p200.air_gap(10) if not REUSE_ETOH_TIPS: p200.drop_tip() if trash_tips else p200.return_tip() - ctx.delay(seconds=10) + protocol.delay(seconds=10) # Remove the ethanol wash for x, i in enumerate(samp_list_2): tip_track(p200, tip_count) p200.aspirate(155, i) p200.air_gap(10) p200.dispense(p200.current_volume, this_waste_res) - ctx.delay(seconds=1) + protocol.delay(seconds=1) p200.air_gap(10) if trash_tips: p200.drop_tip() - ctx.comment("****Dropping Tip in Waste shoot****") + protocol.comment("****Dropping Tip in Waste shoot****") else: p200.return_tip() - ctx.comment("****Dropping Tip Back in Tip Box****") + protocol.comment("****Dropping Tip Back in Tip Box****") p200.flow_rate.aspirate = 150 p200.flow_rate.dispense = 150 # Washes Complete, Move on to Drying Steps - ctx.delay(minutes=3, msg="Allow 3 minutes for residual ethanol to dry") + protocol.delay(minutes=3, msg="Allow 3 minutes for residual ethanol to dry") - ctx.comment("****Moving sample plate off of Magnet****") - ctx.move_labware(sample_plate_2, "D1", use_gripper=USE_GRIPPER) + protocol.comment("****Moving sample plate off of Magnet****") + protocol.move_labware(sample_plate_2, "D1", use_gripper=USE_GRIPPER) # Adding RSB and Mixing for col, i in enumerate(samp_list_2): - ctx.comment(f"****Adding RSB to Columns: {col+1}****") + protocol.comment(f"****Adding RSB to Columns: {col+1}****") tip_track(p50, tip_count) p50.aspirate(rsb_vol_2, rsb_res) p50.air_gap(5) @@ -912,23 +916,23 @@ def lib_cleanup_2() -> None: p50.air_gap(5) if REUSE_RSB_TIPS: p50.return_tip() - ctx.comment("****Dropping Tip Back in Tip Box****") + protocol.comment("****Dropping Tip Back in Tip Box****") else: if trash_tips: p50.drop_tip() - ctx.comment("****Dropping Tip in Waste shoot****") + protocol.comment("****Dropping Tip in Waste shoot****") else: p50.return_tip() - ctx.comment("****Dropping Tip Back in Tip Box****") + protocol.comment("****Dropping Tip Back in Tip Box****") - ctx.delay( + protocol.delay( minutes=3, msg="Allow 3 minutes for incubation and liquid aggregation." ) - ctx.comment("****Move Samples to Magnet for Pelleting****") - ctx.move_labware(sample_plate_2, magblock, use_gripper=USE_GRIPPER) + protocol.comment("****Move Samples to Magnet for Pelleting****") + protocol.move_labware(sample_plate_2, magblock, use_gripper=USE_GRIPPER) - ctx.delay(minutes=2, msg="Please allow 2 minutes for beads to pellet.") + protocol.delay(minutes=2, msg="Please allow 2 minutes for beads to pellet.") p200.flow_rate.aspirate = 10 for i_int, (s, e) in enumerate(zip(samp_list_2, samples_flp)): @@ -939,10 +943,10 @@ def lib_cleanup_2() -> None: p50.air_gap(5) if trash_tips: p50.drop_tip() - ctx.comment("****Dropping Tip in Waste shoot****") + protocol.comment("****Dropping Tip in Waste shoot****") else: p50.return_tip() - ctx.comment("****Dropping Tip Back in Tip Box****") + protocol.comment("****Dropping Tip Back in Tip Box****") # Set Block Temp for Final Plate tc_mod.set_block_temperature(4) @@ -963,4 +967,6 @@ def lib_cleanup_2() -> None: waste2_res = waste2[0] end_probed_wells = [waste1_res, waste2_res] - helpers.find_liquid_height_of_all_wells(ctx, p50, end_probed_wells) + helpers.find_liquid_height_of_all_wells(protocol, p50, end_probed_wells) + if deactivate_mods: + helpers.deactivate_modules(protocol) diff --git a/abr-testing/abr_testing/protocols/active_protocols/1_Simple Normalize Long Right.py b/abr-testing/abr_testing/protocols/active_protocols/1_Simple Normalize Long Right.py index 525a82c3095..6162e6ab34e 100644 --- a/abr-testing/abr_testing/protocols/active_protocols/1_Simple Normalize Long Right.py +++ b/abr-testing/abr_testing/protocols/active_protocols/1_Simple Normalize Long Right.py @@ -4,10 +4,12 @@ ParameterContext, Labware, SINGLE, + ALL, InstrumentContext, Well, ) from abr_testing.protocols import helpers +from typing import List, Dict metadata = { "protocolName": "Simple Normalize Long with LPD and Single Tip", @@ -15,16 +17,14 @@ "source": "Protocol Library", } -requirements = { - "robotType": "Flex", - "apiLevel": "2.21", -} +requirements = {"robotType": "Flex", "apiLevel": "2.21"} def add_parameters(parameters: ParameterContext) -> None: """Parameters.""" helpers.create_single_pipette_mount_parameter(parameters) - helpers.create_tip_size_parameter(parameters) + helpers.create_csv_parameter(parameters) + helpers.create_dot_bottom_parameter(parameters) def get_next_tip_by_row(tip_rack: Labware, pipette: InstrumentContext) -> Well | None: @@ -79,149 +79,68 @@ def get_next_tip_by_row(tip_rack: Labware, pipette: InstrumentContext) -> Well | def run(protocol: ProtocolContext) -> None: """Protocol.""" - tip_type = protocol.params.tip_size # type: ignore[attr-defined] + dot_bottom = protocol.params.dot_bottom # type: ignore[attr-defined] mount_pos = protocol.params.pipette_mount # type: ignore[attr-defined] + all_data = protocol.params.parameters_csv.parse_as_csv() # type: ignore[attr-defined] + data = all_data[1:] + helpers.comment_protocol_version(protocol, "01") # DECK SETUP AND LABWARE protocol.comment("THIS IS A NO MODULE RUN") - tiprack_x_1 = protocol.load_labware(tip_type, "D1") - tiprack_x_2 = protocol.load_labware(tip_type, "D2") - tiprack_x_3 = protocol.load_labware(tip_type, "B1") + tiprack_x_1 = protocol.load_labware("opentrons_flex_96_tiprack_200ul", "D1") + tiprack_x_2 = protocol.load_labware("opentrons_flex_96_tiprack_200ul", "D2") + tiprack_x_3 = protocol.load_labware("opentrons_flex_96_tiprack_200ul", "A1") sample_plate_1 = protocol.load_labware( "armadillo_96_wellplate_200ul_pcr_full_skirt", "D3" ) reservoir = protocol.load_labware("nest_12_reservoir_15ml", "B3") + waste_reservoir = protocol.load_labware( + "nest_1_reservoir_195ml", "C1", "Liquid Waste" + ) sample_plate_2 = protocol.load_labware( "armadillo_96_wellplate_200ul_pcr_full_skirt", "C2" ) sample_plate_3 = protocol.load_labware( "armadillo_96_wellplate_200ul_pcr_full_skirt", "B2" ) + sample_plate_4 = protocol.load_labware( + "armadillo_96_wellplate_200ul_pcr_full_skirt", "A2" + ) protocol.load_trash_bin("A3") - # reagent + # reagentg146 Dye_1 = reservoir["A1"] Dye_2 = reservoir["A2"] Dye_3 = reservoir["A3"] Diluent_1 = reservoir["A4"] Diluent_2 = reservoir["A5"] + Diluent_3 = reservoir["A6"] # pipette p1000 = protocol.load_instrument( "flex_8channel_1000", mount_pos, liquid_presence_detection=True ) + p1000_single = protocol.load_instrument( + "flex_1channel_1000", + "right", + liquid_presence_detection=True, + tip_racks=[tiprack_x_2, tiprack_x_3], + ) # LOAD LIQUIDS liquid_volumes = [675.0, 675.0, 675.0, 675.0, 675.0] - wells = [Dye_1, Dye_2, Dye_3, Diluent_1, Diluent_2] + wells = [Dye_1, Dye_2, Dye_3, Diluent_1, Diluent_2, Diluent_3] helpers.load_wells_with_water(protocol, wells, liquid_volumes) - + liquid_vols_and_wells: Dict[str, List[Dict[str, Well | List[Well] | float]]] = { + "Dye": [{"well": [Dye_1, Dye_2, Dye_3], "volume": 675.0}], + "Diluent": [{"well": [Diluent_1, Diluent_2, Diluent_3], "volume": 675.0}], + } current_rack = tiprack_x_1 # CONFIGURE SINGLE LAYOUT - p1000.configure_nozzle_layout( - style=SINGLE, start="H1", tip_racks=[tiprack_x_1, tiprack_x_2, tiprack_x_3] + p1000.configure_nozzle_layout(style=SINGLE, start="H1", tip_racks=[tiprack_x_1]) + helpers.find_liquid_height_of_loaded_liquids( + protocol, liquid_vols_and_wells, p1000_single ) - helpers.find_liquid_height_of_all_wells(protocol, p1000, wells) - sample_quant_csv = """ - sample_plate_1, Sample_well,DYE,DILUENT - sample_plate_1,A1,0,100 - sample_plate_1,B1,5,95 - sample_plate_1,C1,10,90 - sample_plate_1,D1,20,80 - sample_plate_1,E1,40,60 - sample_plate_1,F1,15,40 - sample_plate_1,G1,40,20 - sample_plate_1,H1,40,0 - sample_plate_1,A2,35,65 - sample_plate_1,B2,38,42 - sample_plate_1,C2,42,58 - sample_plate_1,D2,32,8 - sample_plate_1,E2,38,12 - sample_plate_1,F2,26,74 - sample_plate_1,G2,31,69 - sample_plate_1,H2,46,4 - sample_plate_1,A3,47,13 - sample_plate_1,B3,42,18 - sample_plate_1,C3,46,64 - sample_plate_1,D3,48,22 - sample_plate_1,E3,26,74 - sample_plate_1,F3,34,66 - sample_plate_1,G3,43,37 - sample_plate_1,H3,20,80 - sample_plate_1,A4,44,16 - sample_plate_1,B4,49,41 - sample_plate_1,C4,48,42 - sample_plate_1,D4,44,16 - sample_plate_1,E4,47,53 - sample_plate_1,F4,47,33 - sample_plate_1,G4,42,48 - sample_plate_1,H4,39,21 - sample_plate_1,A5,30,20 - sample_plate_1,B5,36,14 - sample_plate_1,C5,31,59 - sample_plate_1,D5,38,52 - sample_plate_1,E5,36,4 - sample_plate_1,F5,32,28 - sample_plate_1,G5,35,55 - sample_plate_1,H5,39,1 - sample_plate_1,A6,31,59 - sample_plate_1,B6,20,80 - sample_plate_1,C6,38,2 - sample_plate_1,D6,34,46 - sample_plate_1,E6,30,70 - sample_plate_1,F6,32,58 - sample_plate_1,G6,21,79 - sample_plate_1,H6,38,52 - sample_plate_1,A7,33,27 - sample_plate_1,B7,34,16 - sample_plate_1,C7,40,60 - sample_plate_1,D7,34,26 - sample_plate_1,E7,30,20 - sample_plate_1,F7,44,56 - sample_plate_1,G7,26,74 - sample_plate_1,H7,45,55 - sample_plate_1,A8,39,1 - sample_plate_1,B8,38,2 - sample_plate_1,C8,34,66 - sample_plate_1,D8,39,11 - sample_plate_1,E8,46,54 - sample_plate_1,F8,37,63 - sample_plate_1,G8,38,42 - sample_plate_1,H8,34,66 - sample_plate_1,A9,44,56 - sample_plate_1,B9,39,11 - sample_plate_1,C9,30,70 - sample_plate_1,D9,37,33 - sample_plate_1,E9,46,54 - sample_plate_1,F9,39,21 - sample_plate_1,G9,29,41 - sample_plate_1,H9,23,77 - sample_plate_1,A10,26,74 - sample_plate_1,B10,39,1 - sample_plate_1,C10,31,49 - sample_plate_1,D10,38,62 - sample_plate_1,E10,29,1 - sample_plate_1,F10,21,79 - sample_plate_1,G10,29,41 - sample_plate_1,H10,28,42 - sample_plate_1,A11,15,55 - sample_plate_1,B11,28,72 - sample_plate_1,C11,11,49 - sample_plate_1,D11,34,66 - sample_plate_1,E11,27,73 - sample_plate_1,F11,30,40 - sample_plate_1,G11,33,67 - sample_plate_1,H11,31,39 - sample_plate_1,A12,39,31 - sample_plate_1,B12,47,53 - sample_plate_1,C12,46,54 - sample_plate_1,D12,13,7 - sample_plate_1,E12,34,46 - sample_plate_1,F12,45,35 - sample_plate_1,G12,28,42 - sample_plate_1,H12,37,63 - """ - data = [r.split(",") for r in sample_quant_csv.strip().splitlines() if r][1:] for X in range(1): protocol.comment("==============================================") protocol.comment("Adding Dye Sample Plate 1") @@ -232,8 +151,8 @@ def run(protocol: ProtocolContext) -> None: well = get_next_tip_by_row(current_rack, p1000) p1000.pick_up_tip(well) while current < len(data): - CurrentWell = str(data[current][1]) - DyeVol = float(data[current][2]) + CurrentWell = str(data[current][0]) + DyeVol = float(data[current][1]) if DyeVol != 0 and DyeVol < 100: p1000.liquid_presence_detection = False p1000.transfer( @@ -245,7 +164,7 @@ def run(protocol: ProtocolContext) -> None: if DyeVol > 20: wells.append(sample_plate_1.wells_by_name()[CurrentWell]) current += 1 - p1000.blow_out() + p1000.blow_out(location=waste_reservoir["A1"]) p1000.touch_tip() p1000.drop_tip() p1000.liquid_presence_detection = True @@ -256,34 +175,34 @@ def run(protocol: ProtocolContext) -> None: current = 0 while current < len(data): - CurrentWell = str(data[current][1]) + CurrentWell = str(data[current][0]) DilutionVol = float(data[current][2]) if DilutionVol != 0 and DilutionVol < 100: well = get_next_tip_by_row(current_rack, p1000) p1000.pick_up_tip(well) - p1000.aspirate(DilutionVol, Diluent_1.bottom(z=2)) + p1000.aspirate(DilutionVol, Diluent_1.bottom(z=dot_bottom)) p1000.dispense( DilutionVol, sample_plate_1.wells_by_name()[CurrentWell].top(z=0.2) ) if DilutionVol > 20: wells.append(sample_plate_1.wells_by_name()[CurrentWell]) - p1000.blow_out() + p1000.blow_out(location=waste_reservoir["A1"]) p1000.touch_tip() p1000.drop_tip() current += 1 + protocol.comment("Changing pipette configuration to 8ch.") + protocol.comment("==============================================") protocol.comment("Adding Dye Sample Plate 2") protocol.comment("==============================================") - current = 0 - well = get_next_tip_by_row(tiprack_x_2, p1000) - p1000.pick_up_tip(well) + p1000_single.pick_up_tip() while current < len(data): - CurrentWell = str(data[current][1]) - DyeVol = float(data[current][2]) + CurrentWell = str(data[current][0]) + DyeVol = float(data[current][1]) if DyeVol != 0 and DyeVol < 100: - p1000.transfer( + p1000_single.transfer( DyeVol, Dye_2.bottom(z=2), sample_plate_2.wells_by_name()[CurrentWell].top(z=1), @@ -292,9 +211,9 @@ def run(protocol: ProtocolContext) -> None: if DyeVol > 20: wells.append(sample_plate_2.wells_by_name()[CurrentWell]) current += 1 - p1000.blow_out() - p1000.touch_tip() - p1000.drop_tip() + p1000_single.blow_out(location=waste_reservoir["A1"]) + p1000_single.touch_tip() + p1000_single.return_tip() protocol.comment("==============================================") protocol.comment("Adding Diluent Sample Plate 2") @@ -302,20 +221,19 @@ def run(protocol: ProtocolContext) -> None: current = 0 while current < len(data): - CurrentWell = str(data[current][1]) + CurrentWell = str(data[current][0]) DilutionVol = float(data[current][2]) if DilutionVol != 0 and DilutionVol < 100: - well = get_next_tip_by_row(tiprack_x_2, p1000) - p1000.pick_up_tip(well) - p1000.aspirate(DilutionVol, Diluent_2.bottom(z=2)) - p1000.dispense( + p1000_single.pick_up_tip() + p1000_single.aspirate(DilutionVol, Diluent_2.bottom(z=dot_bottom)) + p1000_single.dispense( DilutionVol, sample_plate_2.wells_by_name()[CurrentWell].top(z=0.2) ) if DilutionVol > 20: wells.append(sample_plate_2.wells_by_name()[CurrentWell]) - p1000.blow_out() - p1000.touch_tip() - p1000.drop_tip() + p1000_single.blow_out(location=waste_reservoir["A1"]) + p1000_single.touch_tip() + p1000_single.return_tip() current += 1 protocol.comment("==============================================") @@ -323,14 +241,13 @@ def run(protocol: ProtocolContext) -> None: protocol.comment("==============================================") current = 0 - well = get_next_tip_by_row(tiprack_x_3, p1000) - p1000.pick_up_tip(well) + p1000_single.pick_up_tip() while current < len(data): - CurrentWell = str(data[current][1]) - DyeVol = float(data[current][2]) + CurrentWell = str(data[current][0]) + DyeVol = float(data[current][1]) if DyeVol != 0 and DyeVol < 100: - p1000.liquid_presence_detection = False - p1000.transfer( + p1000_single.liquid_presence_detection = False + p1000_single.transfer( DyeVol, Dye_3.bottom(z=2), sample_plate_3.wells_by_name()[CurrentWell].top(z=1), @@ -341,14 +258,85 @@ def run(protocol: ProtocolContext) -> None: if DyeVol > 20: wells.append(sample_plate_3.wells_by_name()[CurrentWell]) current += 1 - p1000.liquid_presence_detection = True - p1000.blow_out() - p1000.touch_tip() - p1000.drop_tip() + p1000_single.liquid_presence_detection = True + p1000_single.blow_out(location=waste_reservoir["A1"]) + p1000_single.touch_tip() + p1000_single.return_tip() protocol.comment("==============================================") protocol.comment("Adding Diluent Sample Plate 3") protocol.comment("==============================================") + current = 0 + while current < len(data): + CurrentWell = str(data[current][0]) + DilutionVol = float(data[current][2]) + if DilutionVol != 0 and DilutionVol < 100: + p1000_single.pick_up_tip() + p1000_single.aspirate(DilutionVol, Diluent_3.bottom(z=dot_bottom)) + p1000_single.dispense( + DilutionVol, sample_plate_3.wells_by_name()[CurrentWell].top(z=0.2) + ) + if DilutionVol > 20: + wells.append(sample_plate_3.wells_by_name()[CurrentWell]) + p1000_single.blow_out(location=waste_reservoir["A1"]) + p1000_single.touch_tip() + p1000_single.return_tip() + current += 1 + protocol.comment("==============================================") + protocol.comment("Adding Dye Sample Plate 4") + protocol.comment("==============================================") + p1000_single.reset_tipracks() current = 0 - # Probe heights - helpers.find_liquid_height_of_all_wells(protocol, p1000, wells) + p1000_single.pick_up_tip() + while current < len(data): + CurrentWell = str(data[current][0]) + DyeVol = float(data[current][1]) + if DyeVol != 0 and DyeVol < 100: + p1000_single.liquid_presence_detection = False + p1000_single.transfer( + DyeVol, + Dye_3.bottom(z=2), + sample_plate_4.wells_by_name()[CurrentWell].top(z=1), + blow_out=True, + blowout_location="destination well", + new_tip="never", + ) + if DyeVol > 20: + wells.append(sample_plate_4.wells_by_name()[CurrentWell]) + current += 1 + p1000_single.liquid_presence_detection = True + p1000_single.blow_out(location=waste_reservoir["A1"]) + p1000_single.touch_tip() + p1000_single.return_tip() + protocol.comment("==============================================") + protocol.comment("Adding Diluent Sample Plate 4") + protocol.comment("==============================================") + current = 0 + while current < len(data): + CurrentWell = str(data[current][0]) + DilutionVol = float(data[current][2]) + if DilutionVol != 0 and DilutionVol < 100: + p1000_single.pick_up_tip() + p1000_single.aspirate(DilutionVol, Diluent_3.bottom(z=dot_bottom)) + p1000_single.dispense( + DilutionVol, sample_plate_4.wells_by_name()[CurrentWell].top(z=0.2) + ) + if DilutionVol > 20: + wells.append(sample_plate_4.wells_by_name()[CurrentWell]) + p1000_single.blow_out(location=waste_reservoir["A1"]) + p1000_single.touch_tip() + p1000_single.return_tip() + current += 1 + + current = 0 + # Probe heights + p1000.configure_nozzle_layout(style=ALL, tip_racks=[tiprack_x_3]) + helpers.clean_up_plates( + p1000, + [sample_plate_1, sample_plate_2, sample_plate_3, sample_plate_4], + waste_reservoir["A1"], + 200, + ) + helpers.find_liquid_height_of_all_wells( + protocol, p1000_single, [waste_reservoir["A1"]] + ) 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 24e7358f6e1..3b11b51b7fe 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 @@ -5,7 +5,7 @@ ThermocyclerContext, TemperatureModuleContext, ) -from opentrons.protocol_api import SINGLE, Well +from opentrons.protocol_api import SINGLE, Well, ALL from abr_testing.protocols import helpers from typing import List, Dict @@ -14,7 +14,7 @@ "protocolName": "PCR Protocol with TC Auto Sealing Lid", "author": "Rami Farawi None: @@ -23,81 +23,79 @@ def add_parameters(parameters: ParameterContext) -> None: helpers.create_disposable_lid_parameter(parameters) helpers.create_csv_parameter(parameters) helpers.create_tc_lid_deck_riser_parameter(parameters) + helpers.create_deactivate_modules_parameter(parameters) -def run(ctx: ProtocolContext) -> None: +def run(protocol: ProtocolContext) -> None: """Protocol.""" - 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] + pipette_mount = protocol.params.pipette_mount # type: ignore[attr-defined] + disposable_lid = protocol.params.disposable_lid # type: ignore[attr-defined] + parsed_csv = protocol.params.parameters_csv.parse_as_csv() # type: ignore[attr-defined] + deck_riser = protocol.params.deck_riser # type: ignore[attr-defined] + deactivate_modules_bool = protocol.params.deactivate_modules # type: ignore[attr-defined] + helpers.comment_protocol_version(protocol, "01") rxn_vol = 50 real_mode = True # DECK SETUP AND LABWARE - tc_mod: ThermocyclerContext = ctx.load_module( + tc_mod: ThermocyclerContext = protocol.load_module( helpers.tc_str ) # type: ignore[assignment] tc_mod.open_lid() tc_mod.set_lid_temperature(105) - temp_mod: TemperatureModuleContext = ctx.load_module( + temp_mod: TemperatureModuleContext = protocol.load_module( helpers.temp_str, location="D3" ) # type: ignore[assignment] reagent_rack = temp_mod.load_labware( - "opentrons_24_aluminumblock_nest_1.5ml_snapcap" - ) # check if 2mL - - dest_plate = tc_mod.load_labware( - "opentrons_96_wellplate_200ul_pcr_full_skirt" - ) # do I change this to tough plate if they run pcr? - - source_plate = ctx.load_labware( - "opentrons_96_wellplate_200ul_pcr_full_skirt", location="D1" - ) # do I change this to their plate? + "opentrons_24_aluminumblock_nest_1.5ml_snapcap", "Reagent Rack" + ) + dest_plate_1 = tc_mod.load_labware( + "opentrons_96_wellplate_200ul_pcr_full_skirt", "Destination Plate 1" + ) + source_plate_1 = protocol.load_labware( + "opentrons_96_wellplate_200ul_pcr_full_skirt", "D1", "DNA Plate 1" + ) + waste = protocol.load_labware("nest_1_reservoir_195ml", "D2", "Liquid Waste") + liquid_waste = waste["A1"] tiprack_50 = [ - ctx.load_labware("opentrons_flex_96_tiprack_50ul", slot) for slot in [8, 9] + protocol.load_labware("opentrons_flex_96_tiprack_50ul", slot) for slot in [8, 9] ] # Opentrons tough pcr auto sealing lids if disposable_lid: - unused_lids = helpers.load_disposable_lids(ctx, 3, ["C3"], deck_riser) + unused_lids = helpers.load_disposable_lids(protocol, 3, ["C3"], deck_riser) used_lids: List[Labware] = [] # LOAD PIPETTES - p50 = ctx.load_instrument( + p50 = protocol.load_instrument( "flex_8channel_50", pipette_mount, tip_racks=tiprack_50, liquid_presence_detection=True, ) p50.configure_nozzle_layout(style=SINGLE, start="A1", tip_racks=tiprack_50) - ctx.load_trash_bin("A3") + protocol.load_trash_bin("A3") temp_mod.set_temperature(4) # LOAD LIQUIDS water: Well = reagent_rack["B1"] mmx_pic: List[Well] = reagent_rack.rows()[0] - dna_pic: List[Well] = source_plate.wells() + dna_pic: List[Well] = source_plate_1.wells() liquid_vols_and_wells: Dict[str, List[Dict[str, Well | List[Well] | float]]] = { - "Water": [{"well": water, "volume": 1500.0}], - "Mastermix": [{"well": mmx_pic, "volume": 1500.0}], - "DNA": [{"well": dna_pic, "volume": 50.0}], + "Water": [{"well": water, "volume": 500.0}], + "Mastermix": [{"well": mmx_pic, "volume": 500.0}], + "DNA": [{"well": dna_pic, "volume": 100.0}], } - helpers.load_wells_with_custom_liquids(ctx, liquid_vols_and_wells) - wells_to_probe = [[water], mmx_pic, dna_pic] - wells_to_probe_flattened = [ - well for list_of_wells in wells_to_probe for well in list_of_wells - ] - helpers.find_liquid_height_of_all_wells(ctx, p50, wells_to_probe_flattened) + helpers.find_liquid_height_of_loaded_liquids(protocol, liquid_vols_and_wells, p50) # adding water - ctx.comment("\n\n----------ADDING WATER----------\n") + protocol.comment("\n\n----------ADDING WATER----------\n") p50.pick_up_tip() - # p50.aspirate(40, water) # prewet - # p50.dispense(40, water) + p50.aspirate(40, water) # prewet + p50.dispense(40, water) parsed_csv = parsed_csv[1:] num_of_rows = len(parsed_csv) for row_index in range(num_of_rows): @@ -112,13 +110,13 @@ def run(ctx: ProtocolContext) -> None: p50.configure_for_volume(water_vol) p50.aspirate(water_vol, water) - p50.dispense(water_vol, dest_plate[dest_well], rate=0.5) + p50.dispense(water_vol, dest_plate_1[dest_well], rate=0.5) p50.configure_for_volume(50) - # p50.blow_out() + p50.blow_out() p50.drop_tip() # adding Mastermix - ctx.comment("\n\n----------ADDING MASTERMIX----------\n") + protocol.comment("\n\n----------ADDING MASTERMIX----------\n") for i, row in enumerate(parsed_csv): p50.pick_up_tip() mmx_vol = row[3] @@ -144,8 +142,8 @@ def run(ctx: ProtocolContext) -> None: break p50.configure_for_volume(mmx_vol) p50.aspirate(mmx_vol, reagent_rack[mmx_tube]) - p50.dispense(mmx_vol, dest_plate[dest_well].top()) - ctx.delay(seconds=2) + p50.dispense(mmx_vol, dest_plate_1[dest_well].top()) + protocol.delay(seconds=2) p50.blow_out() p50.touch_tip() p50.configure_for_volume(50) @@ -154,7 +152,7 @@ def run(ctx: ProtocolContext) -> None: p50.drop_tip() # adding DNA - ctx.comment("\n\n----------ADDING DNA----------\n") + protocol.comment("\n\n----------ADDING DNA----------\n") for row in parsed_csv: dna_vol = row[2] if dna_vol.lower() == "x": @@ -168,29 +166,28 @@ def run(ctx: ProtocolContext) -> None: if dna_vol == 0: break p50.configure_for_volume(dna_vol) - p50.aspirate(dna_vol, source_plate[dest_and_source_well]) - p50.dispense(dna_vol, dest_plate[dest_and_source_well], rate=0.5) + p50.aspirate(dna_vol, source_plate_1[dest_and_source_well]) + p50.dispense(dna_vol, dest_plate_1[dest_and_source_well], rate=0.5) p50.mix( 10, 0.7 * rxn_vol if 0.7 * rxn_vol < 30 else 30, - dest_plate[dest_and_source_well], + dest_plate_1[dest_and_source_well], ) p50.drop_tip() p50.configure_for_volume(50) - wells_to_probe_flattened.append(dest_plate[dest_well]) - ctx.comment("\n\n-----------Running PCR------------\n") + protocol.comment("\n\n-----------Running PCR------------\n") if real_mode: if disposable_lid: lid_on_plate, unused_lids, used_lids = helpers.use_disposable_lid_with_tc( - ctx, unused_lids, used_lids, dest_plate, tc_mod + protocol, unused_lids, used_lids, dest_plate_1, tc_mod ) else: tc_mod.close_lid() helpers.perform_pcr( - ctx, + protocol, tc_mod, initial_denature_time_sec=120, denaturation_time_sec=10, @@ -205,9 +202,16 @@ def run(ctx: ProtocolContext) -> None: tc_mod.open_lid() if disposable_lid: if len(used_lids) <= 1: - ctx.move_labware(lid_on_plate, "C2", use_gripper=True) + protocol.move_labware(lid_on_plate, "C2", use_gripper=True) else: - ctx.move_labware(lid_on_plate, used_lids[-2], use_gripper=True) + protocol.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) + mmx_pic.append(water) + # Empty plates into liquid waste + p50.configure_nozzle_layout(style=ALL, tip_racks=tiprack_50) + helpers.clean_up_plates(p50, [source_plate_1, dest_plate_1], liquid_waste, 50) + # Probe liquid waste + helpers.find_liquid_height_of_all_wells(protocol, p50, [liquid_waste]) + if deactivate_modules_bool: + helpers.deactivate_modules(protocol) diff --git a/abr-testing/abr_testing/protocols/active_protocols/3_Tartrazine Protocol.py b/abr-testing/abr_testing/protocols/active_protocols/3_Tartrazine Protocol.py index 66db85468f4..9916ef7f7fc 100644 --- a/abr-testing/abr_testing/protocols/active_protocols/3_Tartrazine Protocol.py +++ b/abr-testing/abr_testing/protocols/active_protocols/3_Tartrazine Protocol.py @@ -1,5 +1,10 @@ """Tartrazine Protocol.""" -from opentrons.protocol_api import ProtocolContext, ParameterContext, Well +from opentrons.protocol_api import ( + ProtocolContext, + ParameterContext, + Well, + InstrumentContext, +) from abr_testing.protocols import helpers from opentrons.protocol_api.module_contexts import ( AbsorbanceReaderContext, @@ -23,101 +28,172 @@ def add_parameters(parameters: ParameterContext) -> None: parameters.add_int( variable_name="number_of_plates", display_name="Number of Plates", - default=4, + default=1, minimum=1, maximum=4, ) + helpers.create_channel_parameter(parameters) + helpers.create_plate_reader_compatible_labware_parameter(parameters) -def run(ctx: ProtocolContext) -> None: +def run(protocol: ProtocolContext) -> None: """Protocol.""" - number_of_plates = ctx.params.number_of_plates # type: ignore [attr-defined] + # Load parameters + number_of_plates = protocol.params.number_of_plates # type: ignore [attr-defined] + channels = protocol.params.channels # type: ignore [attr-defined] + plate_type = protocol.params.labware_plate_reader_compatible # type: ignore [attr-defined] + + helpers.comment_protocol_version(protocol, "01") # Plate Reader - plate_reader: AbsorbanceReaderContext = ctx.load_module( + plate_reader: AbsorbanceReaderContext = protocol.load_module( helpers.abs_mod_str, "A3" ) # type: ignore[assignment] - hs: HeaterShakerContext = ctx.load_module(helpers.hs_str, "A1") # type: ignore[assignment] - hs_adapter = hs.load_adapter("opentrons_universal_flat_adapter") - tube_rack = ctx.load_labware( - "opentrons_10_tuberack_nest_4x50ml_6x15ml_conical", "C2", "Reagent Tube" - ) - tartrazine_tube = tube_rack["A3"] - water_tube_1 = tube_rack["A4"] - water_tube_2 = tube_rack["B3"] - sample_plate_1 = ctx.load_labware( - "corning_96_wellplate_360ul_flat", "D1", "Sample Plate 1" - ) - sample_plate_2 = ctx.load_labware( - "corning_96_wellplate_360ul_flat", "D2", "Sample Plate 2" + hs: HeaterShakerContext = protocol.load_module(helpers.hs_str, "A1") # type: ignore[assignment] + # Load Plates based off of number_of_plates parameter + available_deck_slots = ["D1", "D2", "C1", "B1"] + sample_plate_list = [] + for plate_num, slot in zip(range(number_of_plates), available_deck_slots): + plate = protocol.load_labware(plate_type, slot, f"Sample Plate {plate_num + 1}") + sample_plate_list.append(plate) + available_tip_rack_slots = ["D3", "C3", "B3", "B2"] + # LOAD PIPETTES AND TIP RACKS + # 50 CHANNEL + tip_racks_50 = [] + for plate_num, slot_2 in zip(range(number_of_plates), available_tip_rack_slots): + tiprack_50 = protocol.load_labware("opentrons_flex_96_tiprack_50ul", slot_2) + tip_racks_50.append(tiprack_50) + p50 = protocol.load_instrument( + f"flex_{channels}_50", "left", tip_racks=tip_racks_50 ) - sample_plate_3 = ctx.load_labware( - "corning_96_wellplate_360ul_flat", "C1", "Sample Plate 3" - ) - sample_plate_4 = ctx.load_labware( - "corning_96_wellplate_360ul_flat", "B1", "Sample Plate 4" + # 1000 CHANNEL + tiprack_1000_1 = protocol.load_labware("opentrons_flex_96_tiprack_1000ul", "A2") + p1000 = protocol.load_instrument( + f"flex_{channels}_1000", "right", tip_racks=[tiprack_1000_1] ) + # DETERMINE RESERVOIR BASED OFF # OF PIPETTE CHANNELS + # 1 CHANNEL = TUBE RACK + if p50.active_channels == 1: + reservoir = protocol.load_labware( + "opentrons_10_tuberack_nest_4x50ml_6x15ml_conical", "C2", "Reservoir" + ) + water_max_vol = reservoir["A3"].max_volume - 500 + reservoir_wells = reservoir.wells()[6:] # Skip first 4 bc they are 15ml + else: + # 8 CHANNEL = 12 WELL RESERVOIR + reservoir = protocol.load_labware("nest_12_reservoir_15ml", "C2", "Reservoir") + water_max_vol = reservoir["A1"].max_volume - 500 + reservoir_wells = reservoir.wells()[ + 1: + ] # Skip A1 as it's reserved for tartrazine - sample_plate_list = [sample_plate_1, sample_plate_2, sample_plate_3, sample_plate_4] - tiprack_50_1 = ctx.load_labware("opentrons_flex_96_tiprack_50ul", "D3") - tiprack_50_2 = ctx.load_labware("opentrons_flex_96_tiprack_50ul", "C3") - tiprack_50_3 = ctx.load_labware("opentrons_flex_96_tiprack_50ul", "B3") - tiprack_1000_1 = ctx.load_labware("opentrons_flex_96_tiprack_1000ul", "A2") - tip_racks = [tiprack_50_1, tiprack_50_2, tiprack_50_3] + # LABEL RESERVOIR WELLS AND DETERMINE NEEDED LIQUID + tartrazine_well = reservoir["A1"] + # NEEDED TARTRAZINE + needed_tartrazine: float = ( + float(number_of_plates) * 96.0 + ) * 10.0 + 1000.0 # loading extra as a safety factor + # NEEDED WATER + needed_water: float = ( + float(number_of_plates) * 96.0 * 250 + ) # loading extra as a safety factor + # CALCULATING NEEDED # OF WATER WELLS + needed_wells = round(needed_water / water_max_vol) + water_wells = [] + for i in range(needed_wells + 1): + water_wells.append(reservoir_wells[i]) - # Pipette - p50 = ctx.load_instrument("flex_1channel_50", "left", tip_racks=tip_racks) - p1000 = ctx.load_instrument( - "flex_1channel_1000", "right", tip_racks=[tiprack_1000_1] - ) + def _mix_tartrazine(pipette: InstrumentContext, well_to_probe: Well) -> None: + """Mix Tartrazine.""" + # Mix step is needed to ensure tartrazine does not settle between plates. + pipette.pick_up_tip() + top_of_tartrazine = helpers.find_liquid_height(pipette, well_to_probe) + for i in range(20): + p50.aspirate(1, well_to_probe.bottom(z=1)) + p50.dispense(1, well_to_probe.bottom(z=top_of_tartrazine + 1)) + pipette.return_tip() - # Probe wells + # LOAD LIQUIDS AND PROBE WELLS liquid_vols_and_wells: Dict[str, List[Dict[str, Well | List[Well] | float]]] = { - "Tartrazine": [{"well": tartrazine_tube, "volume": 45.0}], - "Water": [{"well": [water_tube_1, water_tube_2], "volume": 45.0}], + "Tartrazine": [{"well": tartrazine_well, "volume": needed_tartrazine}], + "Water": [{"well": water_wells, "volume": water_max_vol}], } - helpers.find_liquid_height_of_loaded_liquids(ctx, liquid_vols_and_wells, p50) - + helpers.find_liquid_height_of_loaded_liquids(protocol, liquid_vols_and_wells, p50) + tip_count = 1 * p50.active_channels # number of 50 ul tip uses. + p50.reset_tipracks() i = 0 all_percent_error_dict = {} cv_dict = {} - vol = 0.0 - tip_count = 0 + vol = 0.0 # counter to track available water volume + water_tip_count = 0 * p1000.active_channels # number of 1000 ul tip uses + well_num = 0 # index of well being used for water for sample_plate in sample_plate_list[:number_of_plates]: - deck_locations = ["D1", "D2", "C1", "B1"] - p1000.pick_up_tip() - for well in sample_plate.wells(): - if vol < 45000: - tube_of_choice = water_tube_1 + return_location = sample_plate.parent + # Mix Tartrazine to ensure no settling as occurred + _mix_tartrazine(p50, tartrazine_well) + tip_count += 1 * p50.active_channels + # Determine list of wells to probe + if p50.active_channels == 1: + well_list = sample_plate.wells() + elif p50.active_channels == 8: + well_list = sample_plate.rows()[0] + for well in well_list: + p1000.pick_up_tip() + # Determine which water well to aspirate from. + if vol < water_max_vol - 6000: + well_of_choice = water_wells[well_num] else: - tube_of_choice = water_tube_2 + well_num += 1 + well_of_choice = water_wells[well_num] + vol = 0.0 p50.pick_up_tip() - p1000.aspirate(190, tube_of_choice) - p1000.air_gap(5) - p1000.dispense(5, well.top()) + p1000.aspirate(190, well_of_choice) + p1000.air_gap(10) + p1000.dispense(10, well.top()) p1000.dispense(190, well) - vol += 190 - height = helpers.find_liquid_height(p50, tartrazine_tube) - p50.aspirate(10, tartrazine_tube.bottom(z=height)) + # Two blow outs ensures water is completely removed from pipette + p1000.blow_out(well.top()) + protocol.delay(minutes=0.1) + p1000.blow_out(well.top()) + vol += 190 * p1000.active_channels + # Probe to find liquid height of tartrazine to ensure correct amount is aspirated + height = helpers.find_liquid_height(p50, tartrazine_well) + if height <= 0.0: + # If a negative tartrazine height is found, + # the protocol will pause, prompt a refill, and reprobe. + protocol.pause("Fill tartrazine") + height = helpers.find_liquid_height(p50, tartrazine_well) + p50.aspirate(10, tartrazine_well.bottom(z=height), rate=0.15) p50.air_gap(5) p50.dispense(5, well.top()) - p50.dispense(10, well.bottom(z=0.5)) + p50.dispense(10, well.bottom(z=0.5), rate=0.15) + p50.blow_out() + protocol.delay(minutes=0.1) p50.blow_out() p50.return_tip() - tip_count += 1 - if tip_count >= (96 * 3): + tip_count += p50.active_channels + if tip_count >= (96 * len(tip_racks_50)): p50.reset_tipracks() - p1000.return_tip() - helpers.move_labware_to_hs(ctx, sample_plate, hs, hs_adapter) - helpers.set_hs_speed(ctx, hs, 1500, 2.0, True) + tip_count = 0 + p1000.return_tip() + water_tip_count += p1000.active_channels + if water_tip_count >= 96: + p1000.reset_tipracks() + water_tip_count = 0 + # Move labware to heater shaker to be mixed + helpers.move_labware_to_hs(protocol, sample_plate, hs, hs) + helpers.set_hs_speed(protocol, hs, 1500, 2.0, True) hs.open_labware_latch() + # Initialize plate reader plate_reader.close_lid() plate_reader.initialize("single", [450]) plate_reader.open_lid() - ctx.move_labware(sample_plate, plate_reader, use_gripper=True) + # Move sample plate into plate reader + protocol.move_labware(sample_plate, plate_reader, use_gripper=True) sample_plate_name = "sample plate_" + str(i + 1) csv_string = sample_plate_name + "_" + str(datetime.now()) plate_reader.close_lid() result = plate_reader.read(csv_string) + # Calculate CV and % error of expected value. for wavelength in result: dict_of_wells = result[wavelength] readings_and_wells = dict_of_wells.items() @@ -145,11 +221,15 @@ def run(ctx: ProtocolContext) -> None: "SD": standard_deviation, "Avg Percent Error": avg_percent_error, } + # Move Plate back to original location all_percent_error_dict[sample_plate_name] = percent_error_dict plate_reader.open_lid() - ctx.move_labware(sample_plate, deck_locations[i], use_gripper=True) + protocol.comment( + f"------plate {sample_plate}. {cv_dict[sample_plate_name]}------" + ) + protocol.move_labware(sample_plate, return_location, use_gripper=True) i += 1 # Print percent error dictionary - ctx.comment("Percent Error: " + str(all_percent_error_dict)) + protocol.comment("Percent Error: " + str(all_percent_error_dict)) # Print cv dictionary - ctx.comment("Plate Reader result: " + str(cv_dict)) + protocol.comment("Plate Reader Result: " + str(cv_dict)) diff --git a/abr-testing/abr_testing/protocols/active_protocols/4_Illumina DNA Enrichment.py b/abr-testing/abr_testing/protocols/active_protocols/4_Illumina DNA Enrichment.py new file mode 100644 index 00000000000..ff9a9807c92 --- /dev/null +++ b/abr-testing/abr_testing/protocols/active_protocols/4_Illumina DNA Enrichment.py @@ -0,0 +1,1016 @@ +"""DVT1ABR4: Illumina DNA Enrichment.""" +from opentrons.protocol_api import ( + ParameterContext, + ProtocolContext, + Labware, + Well, + InstrumentContext, +) +from opentrons import types +from abr_testing.protocols import helpers +from opentrons.protocol_api.module_contexts import ( + HeaterShakerContext, + MagneticBlockContext, + ThermocyclerContext, + TemperatureModuleContext, +) +from opentrons.hardware_control.modules.types import ThermocyclerStep +from typing import List, Dict + + +metadata = { + "protocolName": "Illumina DNA Enrichment v4 with TC Auto Sealing Lid", + "author": "Opentrons ", + "source": "Protocol Library", +} + +requirements = { + "robotType": "Flex", + "apiLevel": "2.21", +} + +# SCRIPT SETTINGS +DRYRUN = False # True = skip incubation times, shorten mix, for testing purposes +USE_GRIPPER = True # True = Uses Gripper, False = Manual Move +TIP_TRASH = False # True = Used tips go in Trash, False = Used tips go back into rack +HYBRID_PAUSE = True # True = sets a pause on the Hybridization + +# PROTOCOL SETTINGS +COLUMNS = 4 # 1-4 +HYBRIDDECK = True +HYBRIDTIME = 1.6 # Hours + +# PROTOCOL BLOCKS +STEP_VOLPOOL = 0 +STEP_HYB = 0 +STEP_CAPTURE = 1 +STEP_WASH = 1 +STEP_PCR = 1 +STEP_PCRDECK = 1 +STEP_CLEANUP = 1 + +p200_tips = 0 +p50_tips = 0 +total_waste_volume = 0.0 + + +RUN = 1 + + +def add_parameters(parameters: ParameterContext) -> None: + """Add parameters.""" + helpers.create_hs_speed_parameter(parameters) + helpers.create_dot_bottom_parameter(parameters) + helpers.create_disposable_lid_parameter(parameters) + helpers.create_tc_lid_deck_riser_parameter(parameters) + helpers.create_disposable_lid_trash_location(parameters) + helpers.create_deactivate_modules_parameter(parameters) + + +def run(protocol: ProtocolContext) -> None: + """Protocol.""" + heater_shaker_speed = protocol.params.heater_shaker_speed # type: ignore[attr-defined] + dot_bottom = protocol.params.dot_bottom # type: ignore[attr-defined] + disposable_lid = protocol.params.disposable_lid # type: ignore[attr-defined] + deck_riser = protocol.params.deck_riser # type: ignore[attr-defined] + trash_lid = protocol.params.trash_lid # type: ignore[attr-defined] + deactivate_modules_bool = protocol.params.deactivate_modules # type: ignore[attr-defined] + helpers.comment_protocol_version(protocol, "01") + + unused_lids: List[Labware] = [] + used_lids: List[Labware] = [] + global p200_tips + global p50_tips + + protocol.comment("THIS IS A DRY RUN") if DRYRUN else protocol.comment( + "THIS IS A REACTION RUN" + ) + protocol.comment("USED TIPS WILL GO IN TRASH") if TIP_TRASH else protocol.comment( + "USED TIPS WILL BE RE-RACKED" + ) + + # DECK SETUP AND LABWARE + # ========== FIRST ROW =========== + heatershaker: HeaterShakerContext = protocol.load_module( + helpers.hs_str, "1" + ) # type: ignore[assignment] + heatershaker.close_labware_latch() + sample_plate_2 = heatershaker.load_labware( + "thermoscientificnunc_96_wellplate_1300ul" + ) + reservoir = protocol.load_labware("nest_96_wellplate_2ml_deep", "2", "Liquid Waste") + temp_block: TemperatureModuleContext = protocol.load_module( + helpers.temp_str, "3" + ) # type: ignore[assignment] + reagent_plate, temp_adapter = helpers.load_temp_adapter_and_labware( + "armadillo_96_wellplate_200ul_pcr_full_skirt", temp_block, "Reagent Plate" + ) + # ========== SECOND ROW ========== + MAG_PLATE_SLOT: MagneticBlockContext = protocol.load_module( + helpers.mag_str, "C1" + ) # type: ignore[assignment] + tiprack_200_1 = protocol.load_labware("opentrons_flex_96_tiprack_200ul", "5") + tiprack_50_1 = protocol.load_labware("opentrons_flex_96_tiprack_50ul", "6") + # Opentrons tough pcr auto sealing lids + if disposable_lid: + unused_lids = helpers.load_disposable_lids(protocol, 3, ["C4"], deck_riser) + # ========== THIRD ROW =========== + thermocycler: ThermocyclerContext = protocol.load_module( + helpers.tc_str + ) # type: ignore[assignment] + sample_plate_1 = thermocycler.load_labware( + "armadillo_96_wellplate_200ul_pcr_full_skirt" + ) + thermocycler.open_lid() + tiprack_200_2 = protocol.load_labware("opentrons_flex_96_tiprack_200ul", "8") + tiprack_50_2 = protocol.load_labware("opentrons_flex_96_tiprack_50ul", "9") + # ========== FOURTH ROW ========== + tiprack_200_3 = protocol.load_labware("opentrons_flex_96_tiprack_200ul", "11") + trash_bin = protocol.load_trash_bin("A3") + # reagent + AMPure = reservoir["A1"] + SMB = reservoir["A2"] + + EtOH = reservoir["A4"] + RSB = reservoir["A5"] + Liquid_trash_well_1 = reservoir["A9"] + Liquid_trash_well_2 = reservoir["A10"] + Liquid_trash_well_3 = reservoir["A11"] + Liquid_trash_well_4 = reservoir["A12"] + liquid_trash_list = { + Liquid_trash_well_1: 0.0, + Liquid_trash_well_2: 0.0, + Liquid_trash_well_3: 0.0, + Liquid_trash_well_4: 0.0, + } + + def trash_liquid( + protocol: ProtocolContext, + pipette: InstrumentContext, + vol_to_trash: float, + liquid_trash_list: Dict[Well, float], + ) -> None: + """Determine which wells to use as liquid waste.""" + remaining_volume = vol_to_trash + max_capacity = 1500.0 + # Determine liquid waste location depending on current total volume + # Distribute the liquid volume sequentially + for well, current_volume in liquid_trash_list.items(): + if remaining_volume <= 0.0: + break + available_capacity = max_capacity - current_volume + if available_capacity < remaining_volume: + continue + pipette.dispense(remaining_volume, well.top()) + protocol.delay(minutes=0.1) + pipette.blow_out(well.top()) + liquid_trash_list[well] += remaining_volume + if pipette.current_volume <= 0.0: + break + + # Will Be distributed during the protocol + EEW_1 = sample_plate_2.wells_by_name()["A9"] + EEW_2 = sample_plate_2.wells_by_name()["A10"] + EEW_3 = sample_plate_2.wells_by_name()["A11"] + EEW_4 = sample_plate_2.wells_by_name()["A12"] + + NHB2 = reagent_plate.wells_by_name()["A1"] + Panel = reagent_plate.wells_by_name()["A2"] + EHB2 = reagent_plate.wells_by_name()["A3"] + Elute = reagent_plate.wells_by_name()["A4"] + ET2 = reagent_plate.wells_by_name()["A5"] + PPC = reagent_plate.wells_by_name()["A6"] + EPM = reagent_plate.wells_by_name()["A7"] + + # pipette + p1000 = protocol.load_instrument( + "flex_8channel_1000", + "left", + tip_racks=[tiprack_200_1, tiprack_200_2, tiprack_200_3], + ) + p50 = protocol.load_instrument( + "flex_8channel_50", "right", tip_racks=[tiprack_50_1, tiprack_50_2] + ) + reagent_plate.columns()[3] + # Load liquids and probe + liquid_vols_and_wells: Dict[str, List[Dict[str, Well | List[Well] | float]]] = { + "Reagents": [ + {"well": reagent_plate.columns()[3], "volume": 75.0}, + {"well": reagent_plate.columns()[4], "volume": 15.0}, + {"well": reagent_plate.columns()[5], "volume": 20.0}, + {"well": reagent_plate.columns()[6], "volume": 65.0}, + ], + "AMPure": [{"well": reservoir.columns()[0], "volume": 120.0}], + "SMB": [{"well": reservoir.columns()[1], "volume": 750.0}], + "EtOH": [{"well": reservoir.columns()[3], "volume": 900.0}], + "RSB": [{"well": reservoir.columns()[4], "volume": 96.0}], + "Wash": [ + {"well": sample_plate_2.columns()[8], "volume": 1000.0}, + {"well": sample_plate_2.columns()[9], "volume": 1000.0}, + {"well": sample_plate_2.columns()[10], "volume": 1000.0}, + {"well": sample_plate_2.columns()[11], "volume": 1000.0}, + ], + "Samples": [{"well": sample_plate_1.wells(), "volume": 150.0}], + } + helpers.find_liquid_height_of_loaded_liquids(protocol, liquid_vols_and_wells, p50) + # tip and sample tracking + if COLUMNS == 1: + column_1_list = ["A1"] # Plate 1 + column_2_list = ["A1"] # Plate 2 + column_3_list = ["A4"] # Plate 2 + column_4_list = ["A4"] # Plate 1 + column_5_list = ["A7"] # Plate 2 + column_6_list = ["A7"] # Plate 1 + WASHES = [EEW_1] + if COLUMNS == 2: + column_1_list = ["A1", "A2"] # Plate 1 + column_2_list = ["A1", "A2"] # Plate 2 + column_3_list = ["A4", "A5"] # Plate 2 + column_4_list = ["A4", "A5"] # Plate 1 + column_5_list = ["A7", "A8"] # Plate 2 + column_6_list = ["A7", "A8"] # Plate 1 + WASHES = [EEW_1, EEW_2] + if COLUMNS == 3: + column_1_list = ["A1", "A2", "A3"] # Plate 1 + column_2_list = ["A1", "A2", "A3"] # Plate 2 + column_3_list = ["A4", "A5", "A6"] # Plate 2 + column_4_list = ["A4", "A5", "A6"] # Plate 1 + column_5_list = ["A7", "A8", "A9"] # Plate 2 + column_6_list = ["A7", "A8", "A9"] # Plate 1 + WASHES = [EEW_1, EEW_2, EEW_3] + if COLUMNS == 4: + column_1_list = ["A1", "A2", "A3", "A4"] # Plate 1 + column_2_list = ["A1", "A2", "A3", "A4"] # Plate 2 + column_3_list = ["A5", "A6", "A7", "A8"] # Plate 2 + column_4_list = ["A5", "A6", "A7", "A8"] # Plate 1 + column_5_list = ["A9", "A10", "A11", "A12"] # Plate 2 + column_6_list = ["A9", "A10", "A11", "A12"] # Plate 1 + WASHES = [EEW_1, EEW_2, EEW_3, EEW_4] + + def tipcheck() -> None: + """Tip tracking function.""" + if p200_tips >= 3 * 12: + p1000.reset_tipracks() + p200_tips == 0 + if p50_tips >= 2 * 12: + p50.reset_tipracks() + p50_tips == 0 + + # commands + for loop in range(RUN): + thermocycler.open_lid() + heatershaker.open_labware_latch() + if DRYRUN is False: + if STEP_HYB == 1: + protocol.comment("SETTING THERMO and TEMP BLOCK Temperature") + thermocycler.set_block_temperature(4) + thermocycler.set_lid_temperature(100) + temp_block.set_temperature(4) + else: + protocol.comment("SETTING THERMO and TEMP BLOCK Temperature") + thermocycler.set_block_temperature(58) + thermocycler.set_lid_temperature(58) + heatershaker.set_and_wait_for_temperature(58) + heatershaker.close_labware_latch() + + # Sample Plate contains 30ul of DNA + + if STEP_VOLPOOL == 1: + protocol.comment("==============================================") + protocol.comment("--> Quick Vol Pool") + protocol.comment("==============================================") + + if STEP_HYB == 1: + protocol.comment("==============================================") + protocol.comment("--> HYB") + protocol.comment("==============================================") + + protocol.comment("--> Adding NHB2") + NHB2Vol = 50 + for loop, X in enumerate(column_1_list): + p50.pick_up_tip() + p50.aspirate(NHB2Vol, NHB2.bottom(z=dot_bottom)) # original = () + p50.dispense( + NHB2Vol, sample_plate_1[X].bottom(z=dot_bottom) + ) # original = () + p50.return_tip() if TIP_TRASH is False else p50.drop_tip() + p50_tips += 1 + tipcheck() + + protocol.comment("--> Adding Panel") + PanelVol = 10 + for loop, X in enumerate(column_1_list): + p50.pick_up_tip() + p50.aspirate(PanelVol, Panel.bottom(z=dot_bottom)) # original = () + p50.dispense( + PanelVol, sample_plate_1[X].bottom(z=dot_bottom) + ) # original = () + p50.return_tip() if TIP_TRASH is False else p50.drop_tip() + p50_tips += 1 + tipcheck() + + protocol.comment("--> Adding EHB2") + EHB2Vol = 10 + EHB2MixRep = 10 if DRYRUN is False else 1 + EHB2MixVol = 90 + for loop, X in enumerate(column_1_list): + p1000.pick_up_tip() + p1000.aspirate(EHB2Vol, EHB2.bottom(z=dot_bottom)) # original = () + p1000.dispense( + EHB2Vol, sample_plate_1[X].bottom(z=dot_bottom) + ) # original = () + p1000.move_to(sample_plate_1[X].bottom(z=dot_bottom)) # original = () + p1000.mix(EHB2MixRep, EHB2MixVol) + p1000.return_tip() if TIP_TRASH is False else p1000.drop_tip() + p50_tips += 1 + tipcheck() + + if HYBRIDDECK: + protocol.comment("Hybridize on Deck") + if disposable_lid: + ( + lid_on_plate, + unused_lids, + used_lids, + ) = helpers.use_disposable_lid_with_tc( + protocol, unused_lids, used_lids, sample_plate_1, thermocycler + ) + else: + thermocycler.close_lid() + if DRYRUN is False: + profile_TAGSTOP: List[ThermocyclerStep] = [ + {"temperature": 98, "hold_time_minutes": 5}, + {"temperature": 97, "hold_time_minutes": 1}, + {"temperature": 95, "hold_time_minutes": 1}, + {"temperature": 93, "hold_time_minutes": 1}, + {"temperature": 91, "hold_time_minutes": 1}, + {"temperature": 89, "hold_time_minutes": 1}, + {"temperature": 87, "hold_time_minutes": 1}, + {"temperature": 85, "hold_time_minutes": 1}, + {"temperature": 83, "hold_time_minutes": 1}, + {"temperature": 81, "hold_time_minutes": 1}, + {"temperature": 79, "hold_time_minutes": 1}, + {"temperature": 77, "hold_time_minutes": 1}, + {"temperature": 75, "hold_time_minutes": 1}, + {"temperature": 73, "hold_time_minutes": 1}, + {"temperature": 71, "hold_time_minutes": 1}, + {"temperature": 69, "hold_time_minutes": 1}, + {"temperature": 67, "hold_time_minutes": 1}, + {"temperature": 65, "hold_time_minutes": 1}, + {"temperature": 63, "hold_time_minutes": 1}, + {"temperature": 62, "hold_time_minutes": HYBRIDTIME * 60}, + ] + thermocycler.execute_profile( + steps=profile_TAGSTOP, repetitions=1, block_max_volume=100 + ) + thermocycler.set_block_temperature(62) + if HYBRID_PAUSE: + protocol.comment("HYBRIDIZATION PAUSED") + thermocycler.set_block_temperature(10) + thermocycler.open_lid() + if disposable_lid: + if trash_lid: + protocol.move_labware(lid_on_plate, trash_bin, use_gripper=True) + elif len(used_lids) <= 1: + protocol.move_labware(lid_on_plate, "B4", use_gripper=True) + else: + protocol.move_labware( + lid_on_plate, used_lids[-2], use_gripper=True + ) + else: + protocol.comment("Hybridize off Deck") + + if STEP_CAPTURE == 1: + protocol.comment("==============================================") + protocol.comment("--> Capture") + protocol.comment("==============================================") + # Standard Setup + + if DRYRUN is False: + protocol.comment("SETTING THERMO and TEMP BLOCK Temperature") + thermocycler.set_block_temperature(58) + thermocycler.set_lid_temperature(58) + + if DRYRUN is False: + heatershaker.set_and_wait_for_temperature(58) + + protocol.comment("--> Transfer Hybridization") + TransferSup = 100 + for loop, X in enumerate(column_1_list): + p1000.pick_up_tip() + p1000.move_to(sample_plate_1[X].bottom(z=0.5)) + p1000.aspirate(TransferSup + 1, rate=0.25) + p1000.dispense( + TransferSup + 1, sample_plate_2[column_2_list[loop]].bottom(z=1) + ) + p1000.return_tip() if TIP_TRASH is False else p1000.drop_tip() + p200_tips += 1 + tipcheck() + if disposable_lid: + ( + lid_on_plate, + unused_lids, + used_lids, + ) = helpers.use_disposable_lid_with_tc( + protocol, + unused_lids, + used_lids, + sample_plate_1, + thermocycler, + ) + else: + thermocycler.close_lid() + + protocol.comment("--> ADDING SMB") + SMBVol = 250 + SMBMixRPM = heater_shaker_speed + SMBMixRep = 5.0 if DRYRUN is False else 0.1 # minutes + SMBPremix = 3 if DRYRUN is False else 1 + # ============================== + for loop, X in enumerate(column_2_list): + p1000.pick_up_tip() + p1000.mix(SMBPremix, 200, SMB.bottom(z=1)) + p1000.aspirate(SMBVol / 2, SMB.bottom(z=1), rate=0.25) + p1000.dispense(SMBVol / 2, sample_plate_2[X].top(z=-7), rate=0.25) + p1000.aspirate(SMBVol / 2, SMB.bottom(z=1), rate=0.25) + p1000.dispense(SMBVol / 2, sample_plate_2[X].bottom(z=1), rate=0.25) + p1000.default_speed = 5 + p1000.move_to(sample_plate_2[X].bottom(z=5)) + for Mix in range(2): + p1000.aspirate(100, rate=0.5) + p1000.move_to(sample_plate_2[X].bottom(z=1)) + p1000.aspirate(80, rate=0.5) + p1000.dispense(80, rate=0.5) + p1000.move_to(sample_plate_2[X].bottom(z=5)) + p1000.dispense(100, rate=0.5) + Mix += 1 + p1000.blow_out(sample_plate_2[X].top(z=-7)) + p1000.default_speed = 400 + p1000.move_to(sample_plate_2[X].top(z=5)) + p1000.move_to(sample_plate_2[X].top(z=0)) + p1000.move_to(sample_plate_2[X].top(z=5)) + p1000.return_tip() if TIP_TRASH is False else p1000.drop_tip() + p200_tips += 1 + tipcheck() + # ============================== + helpers.set_hs_speed(protocol, heatershaker, SMBMixRPM, SMBMixRep, True) + + # GRIPPER MOVE sample_plate_2 FROM heatershaker TO MAGPLATE + helpers.move_labware_from_hs_to_destination( + protocol, sample_plate_2, heatershaker, MAG_PLATE_SLOT + ) + + thermocycler.open_lid() + if disposable_lid: + if trash_lid: + protocol.move_labware(lid_on_plate, trash_bin, use_gripper=True) + elif len(used_lids) <= 1: + protocol.move_labware(lid_on_plate, "B4", use_gripper=True) + else: + protocol.move_labware(lid_on_plate, used_lids[-2], use_gripper=True) + + if DRYRUN is False: + protocol.delay(minutes=2) + + protocol.comment("==============================================") + protocol.comment("--> WASH") + protocol.comment("==============================================") + # Setting Labware to Resume at Cleanup 1 + + protocol.comment("--> Remove SUPERNATANT") + for loop, X in enumerate(column_2_list): + p1000.pick_up_tip() + p1000.move_to(sample_plate_2[X].bottom(4)) + p1000.aspirate(200, rate=0.25) + trash_liquid(protocol, p1000, 200.0, liquid_trash_list) + p1000.move_to(sample_plate_2[X].bottom(0.5)) + p1000.aspirate(200, rate=0.25) + trash_liquid(protocol, p1000, 200.0, liquid_trash_list) + p1000.aspirate(20) + p1000.return_tip() if TIP_TRASH is False else p1000.drop_tip() + p200_tips += 1 + tipcheck() + + # GRIPPER MOVE sample_plate_2 FROM MAGPLATE TO heatershaker + helpers.move_labware_to_hs( + protocol, sample_plate_2, heatershaker, heatershaker + ) + + protocol.comment("--> Repeating 6 washes") + washreps = 6 + washcount = 0 + for wash in range(washreps): + + protocol.comment("--> Adding EEW") + EEWVol = 200 + for loop, X in enumerate(column_2_list): + p1000.pick_up_tip() + p1000.aspirate( + EEWVol, WASHES[loop].bottom(z=dot_bottom) + ) # original = () + p1000.dispense( + EEWVol, sample_plate_2[X].bottom(z=dot_bottom) + ) # original = () + p1000.return_tip() if TIP_TRASH is False else p1000.drop_tip() + p200_tips += 1 + tipcheck() + helpers.set_hs_speed( + protocol, heatershaker, int(heater_shaker_speed * 0.9), 4.0, True + ) + heatershaker.open_labware_latch() + + if DRYRUN is False: + protocol.delay(seconds=5 * 60) + + # GRIPPER MOVE sample_plate_2 FROM heatershaker TO MAGPLATE + helpers.move_labware_from_hs_to_destination( + protocol, sample_plate_2, heatershaker, MAG_PLATE_SLOT + ) + + if DRYRUN is False: + protocol.delay(seconds=1 * 60) + + protocol.comment("--> Removing Supernatant") + RemoveSup = 200 + for loop, X in enumerate(column_2_list): + p1000.pick_up_tip() + p1000.move_to(sample_plate_2[X].bottom(z=3.5)) + p1000.aspirate(RemoveSup - 100, rate=0.25) + protocol.delay(minutes=0.1) + p1000.move_to(sample_plate_2[X].bottom(z=0.5)) + p1000.aspirate(100, rate=0.25) + trash_liquid(protocol, p1000, RemoveSup, liquid_trash_list) + p1000.return_tip() if TIP_TRASH is False else p1000.drop_tip() + p200_tips += 1 + tipcheck() + + # ============================================================================================ + # GRIPPER MOVE sample_plate_2 FROM MAGPLATE TO heatershaker + helpers.move_labware_to_hs( + protocol, sample_plate_2, heatershaker, heatershaker + ) + washcount += 1 + + protocol.comment("--> Adding EEW") + EEWVol = 200 + for loop, X in enumerate(column_2_list): + p1000.pick_up_tip() + p1000.aspirate( + EEWVol, WASHES[loop].bottom(z=dot_bottom) + ) # original = () + p1000.dispense( + EEWVol, sample_plate_2[X].bottom(z=dot_bottom) + ) # original = () + p1000.return_tip() if TIP_TRASH is False else p1000.drop_tip() + p200_tips += 1 + tipcheck() + + helpers.set_hs_speed( + protocol, heatershaker, int(heater_shaker_speed * 0.9), 4.0, True + ) + + if DRYRUN is False: + protocol.delay(seconds=1 * 60) + + protocol.comment("--> Transfer Hybridization") + TransferSup = 200 + for loop, X in enumerate(column_2_list): + p1000.pick_up_tip() + p1000.move_to(sample_plate_2[X].bottom(z=0.5)) + p1000.aspirate(TransferSup, rate=0.25) + p1000.dispense( + TransferSup, sample_plate_2[column_3_list[loop]].bottom(z=1) + ) + p1000.return_tip() if TIP_TRASH is False else p1000.drop_tip() + p200_tips += 1 + tipcheck() + + if DRYRUN is False: + protocol.delay(seconds=5 * 60) + + # GRIPPER MOVE sample_plate_2 FROM heatershaker TO MAGPLATE + helpers.move_labware_from_hs_to_destination( + protocol, sample_plate_2, heatershaker, MAG_PLATE_SLOT + ) + if DRYRUN is False: + protocol.delay(seconds=1 * 60) + + protocol.comment("--> Removing Supernatant") + RemoveSup = 200 + for loop, X in enumerate(column_3_list): + p1000.pick_up_tip() + p1000.move_to(sample_plate_2[X].bottom(z=3.5)) + p1000.aspirate(RemoveSup - 100, rate=0.25) + protocol.delay(minutes=0.1) + p1000.move_to(sample_plate_2[X].bottom(z=0.5)) + p1000.aspirate(100, rate=0.25) + p1000.move_to(sample_plate_2[X].top(z=0.5)) + trash_liquid(protocol, p1000, 100, liquid_trash_list) + p1000.aspirate(20) + p1000.return_tip() if TIP_TRASH is False else p1000.drop_tip() + p200_tips += 1 + tipcheck() + + protocol.comment("--> Removing Residual") + for loop, X in enumerate(column_3_list): + p50.pick_up_tip() + p50.move_to(sample_plate_2[X].bottom(z=dot_bottom)) # original = z=0 + p50.aspirate(50, rate=0.25) + p50.default_speed = 200 + trash_liquid(protocol, p50, 50, liquid_trash_list) + p50.return_tip() if TIP_TRASH is False else p50.drop_tip() + p50_tips += 1 + tipcheck() + + protocol.comment("==============================================") + protocol.comment("--> ELUTE") + protocol.comment("==============================================") + + protocol.comment("--> Adding Elute") + EluteVol = 23 + for loop, X in enumerate(column_3_list): + p50.pick_up_tip() + p50.aspirate(EluteVol, Elute.bottom(z=dot_bottom)) # original = () + p50.dispense( + EluteVol, sample_plate_2[X].bottom(z=dot_bottom) + ) # original = () + p50.return_tip() if TIP_TRASH is False else p50.drop_tip() + p50_tips += 1 + tipcheck() + + # ============================================================================================ + # GRIPPER MOVE sample_plate_2 FROM MAGPLATE TO heatershaker + helpers.move_labware_to_hs( + protocol, sample_plate_2, heatershaker, heatershaker + ) + # ============================================================================================ + helpers.set_hs_speed( + protocol, heatershaker, int(heater_shaker_speed * 0.9), 2.0, True + ) + heatershaker.open_labware_latch() + + if DRYRUN is False: + protocol.delay(minutes=2) + + # ============================================================================================ + # GRIPPER MOVE sample_plate_2 FROM heatershaker TO MAGPLATE + helpers.move_labware_from_hs_to_destination( + protocol, sample_plate_2, heatershaker, MAG_PLATE_SLOT + ) + protocol.comment("--> Transfer Elution") + TransferSup = 21 + for loop, X in enumerate(column_3_list): + p50.pick_up_tip() + p50.move_to(sample_plate_2[X].bottom(z=0.5)) + p50.aspirate(TransferSup + 1, rate=0.25) + p50.dispense( + TransferSup + 1, sample_plate_1[column_4_list[loop]].bottom(z=1) + ) + p50.return_tip() if TIP_TRASH is False else p50.drop_tip() + p50_tips += 1 + tipcheck() + + protocol.comment("--> Adding ET2") + ET2Vol = 4 + ET2MixRep = 10 if DRYRUN is False else 1 + ET2MixVol = 20 + for loop, X in enumerate(column_4_list): + p50.pick_up_tip() + p50.aspirate(ET2Vol, ET2.bottom(z=dot_bottom)) # original = () + p50.dispense( + ET2Vol, sample_plate_1[X].bottom(z=dot_bottom) + ) # original = () + p50.move_to(sample_plate_1[X].bottom(z=dot_bottom)) # original = () + p50.mix(ET2MixRep, ET2MixVol) + p50.return_tip() if TIP_TRASH is False else p50.drop_tip() + p50_tips += 1 + tipcheck() + + if STEP_PCR == 1: + protocol.comment("==============================================") + protocol.comment("--> AMPLIFICATION") + protocol.comment("==============================================") + + protocol.comment("--> Adding PPC") + PPCVol = 5 + for loop, X in enumerate(column_4_list): + p50.pick_up_tip() + p50.aspirate(PPCVol, PPC.bottom(z=dot_bottom)) # original = () + p50.dispense( + PPCVol, sample_plate_1[X].bottom(z=dot_bottom) + ) # original = () + p50.return_tip() if TIP_TRASH is False else p50.drop_tip() + p50_tips += 1 + tipcheck() + + protocol.comment("--> Adding EPM") + EPMVol = 20 + EPMMixRep = 10 if DRYRUN is False else 1 + EPMMixVol = 45 + for loop, X in enumerate(column_4_list): + p50.pick_up_tip() + p50.aspirate(EPMVol, EPM.bottom(z=dot_bottom)) # original = () + p50.dispense( + EPMVol, sample_plate_1[X].bottom(z=dot_bottom) + ) # original = () + p50.move_to(sample_plate_1[X].bottom(z=dot_bottom)) # original = () + p50.mix(EPMMixRep, EPMMixVol) + p50.return_tip() if TIP_TRASH is False else p50.drop_tip() + p50_tips += 1 + tipcheck() + + if DRYRUN is False: + heatershaker.deactivate_heater() + + if STEP_PCRDECK == 1: + if DRYRUN is False: + if DRYRUN is False: + if disposable_lid: + ( + lid_on_plate, + unused_lids, + used_lids, + ) = helpers.use_disposable_lid_with_tc( + protocol, + unused_lids, + used_lids, + sample_plate_1, + thermocycler, + ) + else: + thermocycler.close_lid() + profile_PCR_1: List[ThermocyclerStep] = [ + {"temperature": 98, "hold_time_seconds": 45} + ] + thermocycler.execute_profile( + steps=profile_PCR_1, repetitions=1, block_max_volume=50 + ) + profile_PCR_2: List[ThermocyclerStep] = [ + {"temperature": 98, "hold_time_seconds": 30}, + {"temperature": 60, "hold_time_seconds": 30}, + {"temperature": 72, "hold_time_seconds": 30}, + ] + thermocycler.execute_profile( + steps=profile_PCR_2, repetitions=12, block_max_volume=50 + ) + profile_PCR_3: List[ThermocyclerStep] = [ + {"temperature": 72, "hold_time_minutes": 1} + ] + thermocycler.execute_profile( + steps=profile_PCR_3, repetitions=1, block_max_volume=50 + ) + thermocycler.set_block_temperature(10) + + thermocycler.open_lid() + if disposable_lid: + if trash_lid: + protocol.move_labware(lid_on_plate, trash_bin, use_gripper=True) + elif len(used_lids) <= 1: + protocol.move_labware(lid_on_plate, "B4", use_gripper=True) + else: + protocol.move_labware( + lid_on_plate, used_lids[-2], use_gripper=True + ) + + if STEP_CLEANUP == 1: + protocol.comment("==============================================") + protocol.comment("--> Cleanup") + protocol.comment("==============================================") + + # GRIPPER MOVE sample_plate_2 FROM MAGPLATE TO heatershaker + helpers.move_labware_to_hs( + protocol, sample_plate_2, heatershaker, heatershaker + ) + + protocol.comment("--> Transfer Elution") + TransferSup = 45 + for loop, X in enumerate(column_4_list): + p50.pick_up_tip() + p50.move_to(sample_plate_1[X].bottom(z=0.5)) + p50.aspirate(TransferSup + 1, rate=0.25) + p50.dispense( + TransferSup + 1, sample_plate_2[column_5_list[loop]].bottom(z=1) + ) + p50.return_tip() if TIP_TRASH is False else p50.drop_tip() + p50_tips += 1 + tipcheck() + + protocol.comment("--> ADDING AMPure (0.8x)") + AMPureVol = 40.5 + AMPureMixRep = 5.0 if DRYRUN is False else 0.1 + AMPurePremix = 3 if DRYRUN is False else 1 + # ========NEW SINGLE TIP DISPENSE=========== + for loop, X in enumerate(column_5_list): + p1000.pick_up_tip() + p1000.mix(AMPurePremix, AMPureVol + 10, AMPure.bottom(z=1)) + p1000.aspirate(AMPureVol, AMPure.bottom(z=1), rate=0.25) + p1000.dispense(AMPureVol, sample_plate_2[X].bottom(z=1), rate=0.25) + p1000.default_speed = 5 + p1000.move_to(sample_plate_2[X].bottom(z=5)) + for Mix in range(2): + p1000.aspirate(60, rate=0.5) + p1000.move_to(sample_plate_2[X].bottom(z=1)) + p1000.aspirate(60, rate=0.5) + p1000.dispense(60, rate=0.5) + p1000.move_to(sample_plate_2[X].bottom(z=5)) + p1000.dispense(30, rate=0.5) + Mix += 1 + p1000.blow_out(sample_plate_2[X].top(z=2)) + p1000.default_speed = 400 + p1000.move_to(sample_plate_2[X].top(z=5)) + p1000.move_to(sample_plate_2[X].top(z=0)) + p1000.move_to(sample_plate_2[X].top(z=5)) + p1000.return_tip() if TIP_TRASH is False else p1000.drop_tip() + p200_tips += 1 + tipcheck() + # ========NEW HS MIX========================= + helpers.set_hs_speed( + protocol, + heatershaker, + int(heater_shaker_speed * 0.9), + AMPureMixRep, + True, + ) + + # GRIPPER MOVE PLATE FROM HEATER SHAKER TO MAG PLATE + helpers.move_labware_from_hs_to_destination( + protocol, sample_plate_2, heatershaker, MAG_PLATE_SLOT + ) + + if DRYRUN is False: + protocol.delay(minutes=4) + + protocol.comment("--> Removing Supernatant") + RemoveSup = 200 + for loop, X in enumerate(column_5_list): + p1000.pick_up_tip() + p1000.move_to(sample_plate_2[X].bottom(z=3.5)) + p1000.aspirate(RemoveSup - 100, rate=0.25) + protocol.delay(minutes=0.1) + p1000.move_to(sample_plate_2[X].bottom(z=0.5)) + p1000.aspirate(100, rate=0.25) + p1000.default_speed = 5 + p1000.move_to(sample_plate_2[X].top(z=2)) + p1000.default_speed = 200 + trash_liquid(protocol, p1000, 200, liquid_trash_list) + p1000.return_tip() if TIP_TRASH is False else p1000.drop_tip() + p200_tips += 1 + tipcheck() + + for X_times in range(2): + protocol.comment("--> ETOH Wash") + ETOHMaxVol = 150 + for loop, X in enumerate(column_5_list): + p1000.pick_up_tip() + p1000.aspirate(ETOHMaxVol, EtOH.bottom(z=1)) + p1000.move_to(EtOH.top(z=0)) + p1000.move_to(EtOH.top(z=-5)) + p1000.move_to(EtOH.top(z=0)) + p1000.move_to(sample_plate_2[X].top(z=-2)) + p1000.dispense(ETOHMaxVol, rate=1) + protocol.delay(minutes=0.1) + p1000.blow_out() + p1000.move_to(sample_plate_2[X].top(z=5)) + p1000.move_to(sample_plate_2[X].top(z=0)) + p1000.move_to(sample_plate_2[X].top(z=5)) + p1000.return_tip() if TIP_TRASH is False else p1000.drop_tip() + p200_tips += 1 + tipcheck() + + if DRYRUN is False: + protocol.delay(minutes=0.5) + + protocol.comment("--> Remove ETOH Wash") + for loop, X in enumerate(column_5_list): + p1000.pick_up_tip() + p1000.move_to(sample_plate_2[X].bottom(z=3.5)) + p1000.aspirate(RemoveSup - 100, rate=0.25) + protocol.delay(minutes=0.1) + p1000.move_to(sample_plate_2[X].bottom(z=0.5)) + p1000.aspirate(100, rate=0.25) + p1000.default_speed = 5 + p1000.move_to(sample_plate_2[X].top(z=2)) + p1000.default_speed = 200 + trash_liquid(protocol, p1000, RemoveSup, liquid_trash_list) + p1000.return_tip() if TIP_TRASH is False else p1000.drop_tip() + p200_tips += 1 + tipcheck() + + if DRYRUN is False: + protocol.delay(minutes=2) + + protocol.comment("--> Removing Residual ETOH") + for loop, X in enumerate(column_5_list): + p1000.pick_up_tip() + p1000.move_to( + sample_plate_2[X].bottom(z=dot_bottom) + ) # original = (z=0) + p1000.aspirate(50, rate=0.25) + p1000.default_speed = 200 + trash_liquid(protocol, p1000, 50, liquid_trash_list) + p1000.return_tip() if TIP_TRASH is False else p1000.drop_tip() + p200_tips += 1 + tipcheck() + + if DRYRUN is False: + protocol.delay(minutes=1) + + # GRIPPER MOVE PLATE FROM MAG PLATE TO HEATER SHAKER + helpers.move_labware_to_hs( + protocol, sample_plate_2, heatershaker, heatershaker + ) + + protocol.comment("--> Adding RSB") + RSBVol = 32 + RSBMixRep = 1.0 if DRYRUN is False else 0.1 # minutes + for loop, X in enumerate(column_5_list): + p1000.pick_up_tip() + p1000.aspirate(RSBVol, RSB.bottom(z=1)) + + p1000.move_to( + ( + sample_plate_2.wells_by_name()[X] + .center() + .move(types.Point(x=1.3 * 0.8, y=0, z=-4)) + ) + ) + p1000.dispense(RSBVol, rate=1) + p1000.move_to(sample_plate_2.wells_by_name()[X].bottom(z=1)) + p1000.aspirate(RSBVol, rate=1) + p1000.move_to( + ( + sample_plate_2.wells_by_name()[X] + .center() + .move(types.Point(x=0, y=1.3 * 0.8, z=-4)) + ) + ) + p1000.dispense(RSBVol, rate=1) + p1000.move_to(sample_plate_2.wells_by_name()[X].bottom(z=1)) + p1000.aspirate(RSBVol, rate=1) + p1000.move_to( + ( + sample_plate_2.wells_by_name()[X] + .center() + .move(types.Point(x=1.3 * -0.8, y=0, z=-4)) + ) + ) + p1000.dispense(RSBVol, rate=1) + p1000.move_to(sample_plate_2.wells_by_name()[X].bottom(z=1)) + p1000.aspirate(RSBVol, rate=1) + p1000.move_to( + ( + sample_plate_2.wells_by_name()[X] + .center() + .move(types.Point(x=0, y=1.3 * -0.8, z=-4)) + ) + ) + p1000.dispense(RSBVol, rate=1) + p1000.move_to(sample_plate_2.wells_by_name()[X].bottom(z=1)) + p1000.aspirate(RSBVol, rate=1) + p1000.dispense(RSBVol, rate=1) + + p1000.blow_out(sample_plate_2.wells_by_name()[X].center()) + p1000.move_to(sample_plate_2.wells_by_name()[X].top(z=5)) + p1000.move_to(sample_plate_2.wells_by_name()[X].top(z=0)) + p1000.move_to(sample_plate_2.wells_by_name()[X].top(z=5)) + p1000.return_tip() if TIP_TRASH is False else p1000.drop_tip() + p200_tips += 1 + tipcheck() + if DRYRUN is False: + helpers.set_hs_speed( + protocol, + heatershaker, + int(heater_shaker_speed * 0.8), + RSBMixRep, + True, + ) + + # GRIPPER MOVE PLATE FROM HEATER SHAKER TO MAG PLATE + helpers.move_labware_from_hs_to_destination( + protocol, sample_plate_2, heatershaker, MAG_PLATE_SLOT + ) + + if DRYRUN is False: + protocol.delay(minutes=3) + + protocol.comment("--> Transferring Supernatant") + TransferSup = 30 + for loop, X in enumerate(column_5_list): + p1000.pick_up_tip() + p1000.move_to(sample_plate_2[X].bottom(z=0.5)) + p1000.aspirate(TransferSup + 1, rate=0.25) + p1000.dispense( + TransferSup + 1, sample_plate_1[column_6_list[loop]].bottom(z=1) + ) + p1000.return_tip() if TIP_TRASH is False else p1000.drop_tip() + p200_tips += 1 + tipcheck() + liquids_to_probe_at_end = [ + Liquid_trash_well_1, + Liquid_trash_well_2, + Liquid_trash_well_3, + Liquid_trash_well_4, + ] + helpers.find_liquid_height_of_all_wells(protocol, p50, liquids_to_probe_at_end) + if deactivate_modules_bool: + helpers.deactivate_modules(protocol) 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 dc40db7f177..ca7506cf6f0 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 @@ -1,14 +1,14 @@ """96 ch Test Single Tip and Gripper Moves.""" from opentrons.protocol_api import ( - ALL, + COLUMN, SINGLE, + ALL, ParameterContext, ProtocolContext, Labware, ) from opentrons.protocol_api.module_contexts import ( HeaterShakerContext, - MagneticBlockContext, ThermocyclerContext, TemperatureModuleContext, ) @@ -21,7 +21,7 @@ } requirements = { - "robotType": "OT-3", + "robotType": "Flex", "apiLevel": "2.21", } @@ -45,25 +45,31 @@ def add_parameters(parameters: ParameterContext) -> None: helpers.create_dot_bottom_parameter(parameters) helpers.create_disposable_lid_parameter(parameters) helpers.create_tc_lid_deck_riser_parameter(parameters) + helpers.create_deactivate_modules_parameter(parameters) -def run(ctx: ProtocolContext) -> None: +def run(protocol: ProtocolContext) -> None: """Protocol.""" - 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] + b = protocol.params.dot_bottom # type: ignore[attr-defined] + TIPRACK_96_NAME = protocol.params.tip_size # type: ignore[attr-defined] + disposable_lid = protocol.params.disposable_lid # type: ignore[attr-defined] + deck_riser = protocol.params.deck_riser # type: ignore[attr-defined] + deactivate_modules_bool = protocol.params.deactivate_modules # type: ignore[attr-defined] - waste_chute = ctx.load_waste_chute() + waste_chute = protocol.load_waste_chute() + helpers.comment_protocol_version(protocol, "01") - thermocycler: ThermocyclerContext = ctx.load_module(helpers.tc_str) # type: ignore[assignment] - mag: MagneticBlockContext = ctx.load_module(helpers.mag_str, "A3") # type: ignore[assignment] - h_s: HeaterShakerContext = ctx.load_module(helpers.hs_str, "D1") # type: ignore[assignment] - temperature_module: TemperatureModuleContext = ctx.load_module( + thermocycler: ThermocyclerContext = protocol.load_module( + helpers.tc_str + ) # type: ignore[assignment] + h_s: HeaterShakerContext = protocol.load_module( + helpers.hs_str, "D1" + ) # type: ignore[assignment] + temperature_module: TemperatureModuleContext = protocol.load_module( helpers.temp_str, "C1" ) # type: ignore[assignment] if disposable_lid: - unused_lids = helpers.load_disposable_lids(ctx, 3, ["A4"], deck_riser) + unused_lids = helpers.load_disposable_lids(protocol, 3, ["A2"], deck_riser) used_lids: List[Labware] = [] thermocycler.open_lid() h_s.open_labware_latch() @@ -75,16 +81,15 @@ def run(ctx: ProtocolContext) -> None: adapters = [temperature_module_adapter, h_s_adapter] - source_reservoir = ctx.load_labware(RESERVOIR_NAME, "D2") - dest_pcr_plate = ctx.load_labware(PCR_PLATE_96_NAME, "C2") + source_reservoir = protocol.load_labware(RESERVOIR_NAME, "D2") + dest_pcr_plate = protocol.load_labware(PCR_PLATE_96_NAME, "C2") + liquid_waste = protocol.load_labware("nest_1_reservoir_195ml", "B2", "Liquid Waste") - tip_rack_1 = ctx.load_labware( - TIPRACK_96_NAME, "A2", adapter=TIPRACK_96_ADAPTER_NAME + tip_rack_1 = protocol.load_labware( + TIPRACK_96_NAME, "A3", adapter="opentrons_flex_96_tiprack_adapter" ) - tip_rack_adapter = tip_rack_1.parent - - tip_rack_2 = ctx.load_labware(TIPRACK_96_NAME, "C3") - tip_rack_3 = ctx.load_labware(TIPRACK_96_NAME, "C4") + tip_rack_2 = protocol.load_labware(TIPRACK_96_NAME, "C3") + tip_rack_3 = protocol.load_labware(TIPRACK_96_NAME, "C4") tip_racks = [ tip_rack_1, @@ -92,14 +97,16 @@ def run(ctx: ProtocolContext) -> None: tip_rack_3, ] - pipette_96_channel = ctx.load_instrument( + pipette_96_channel = protocol.load_instrument( PIPETTE_96_CHANNEL_NAME, mount="left", tip_racks=tip_racks, liquid_presence_detection=True, ) - water = ctx.define_liquid(name="water", description="H₂O", display_color="#42AB2D") + water = protocol.define_liquid( + name="water", description="H₂O", display_color="#42AB2D" + ) source_reservoir.wells_by_name()["A1"].load_liquid(liquid=water, volume=29000) def run_moves( @@ -123,7 +130,7 @@ def move_to_locations( def reset_labware() -> None: """Reset the labware to the reset location.""" - ctx.move_labware( + protocol.move_labware( labware_to_move, reset_location, use_gripper=use_gripper ) @@ -131,7 +138,9 @@ def reset_labware() -> None: return for location in move_locations: - ctx.move_labware(labware_to_move, location, use_gripper=use_gripper) + protocol.move_labware( + labware_to_move, location, use_gripper=use_gripper + ) if reset_after_each_move: reset_labware() @@ -161,14 +170,13 @@ def test_gripper_moves() -> None: def deck_moves(labware: Labware, reset_location: str) -> None: """Function to perform the movement of labware.""" deck_move_sequence = [ - ["B2"], # Deck Moves + ["B3"], # Deck Moves ["C3"], # Staging Area Slot 3 Moves ["C4", "D4"], # Staging Area Slot 4 Moves [ thermocycler, temperature_module_adapter, h_s_adapter, - mag, ], # Module Moves ] @@ -177,14 +185,13 @@ def deck_moves(labware: Labware, reset_location: str) -> None: def staging_area_slot_3_moves(labware: Labware, reset_location: str) -> None: """Function to perform the movement of labware, starting w/ staging area slot 3.""" staging_area_slot_3_move_sequence = [ - ["B2", "C2"], # Deck Moves + ["B3", "C2"], # Deck Moves [], # Don't have Staging Area Slot 3 open ["C4", "D4"], # Staging Area Slot 4 Moves [ thermocycler, temperature_module_adapter, h_s_adapter, - mag, ], # Module Moves ] @@ -198,14 +205,13 @@ def staging_area_slot_3_moves(labware: Labware, reset_location: str) -> None: def staging_area_slot_4_moves(labware: Labware, reset_location: str) -> None: """Function to perform the movement of labware, starting with staging area slot 4.""" staging_area_slot_4_move_sequence = [ - ["C2", "B2"], # Deck Moves + ["C2", "B3"], # Deck Moves ["C3"], # Staging Area Slot 3 Moves ["C4"], # Staging Area Slot 4 Moves [ thermocycler, temperature_module_adapter, h_s_adapter, - mag, ], # Module Moves ] @@ -219,7 +225,7 @@ def staging_area_slot_4_moves(labware: Labware, reset_location: str) -> None: def module_moves(labware: Labware, module_locations: List) -> None: """Function to perform the movement of labware, starting on a module.""" module_move_sequence = [ - ["C2", "B2"], # Deck Moves + ["C2", "B3"], # Deck Moves ["C3"], # Staging Area Slot 3 Moves ["C4", "D4"], # Staging Area Slot 4 Moves ] @@ -229,7 +235,7 @@ def module_moves(labware: Labware, module_locations: List) -> None: labware_move_to_locations.remove(module_starting_location) all_sequences = module_move_sequence.copy() all_sequences.append(labware_move_to_locations) - ctx.move_labware( + protocol.move_labware( labware, module_starting_location, use_gripper=USING_GRIPPER ) run_moves( @@ -242,27 +248,27 @@ def module_moves(labware: Labware, module_locations: List) -> None: deck_moves(dest_pcr_plate, DECK_MOVE_RESET_LOCATION) - ctx.move_labware( + protocol.move_labware( dest_pcr_plate, STAGING_AREA_SLOT_3_RESET_LOCATION, use_gripper=USING_GRIPPER, ) staging_area_slot_3_moves(dest_pcr_plate, STAGING_AREA_SLOT_3_RESET_LOCATION) - ctx.move_labware( + protocol.move_labware( dest_pcr_plate, STAGING_AREA_SLOT_4_RESET_LOCATION, use_gripper=USING_GRIPPER, ) staging_area_slot_4_moves(dest_pcr_plate, STAGING_AREA_SLOT_4_RESET_LOCATION) - module_locations = [thermocycler, mag] + adapters + module_locations = [thermocycler] + adapters module_moves(dest_pcr_plate, module_locations) - ctx.move_labware(dest_pcr_plate, thermocycler, use_gripper=USING_GRIPPER) + protocol.move_labware(dest_pcr_plate, thermocycler, use_gripper=USING_GRIPPER) def test_manual_moves() -> None: """Test manual moves.""" - ctx.move_labware(source_reservoir, "D4", use_gripper=USING_GRIPPER) + protocol.move_labware(source_reservoir, "D4", use_gripper=USING_GRIPPER) def test_pipetting() -> None: """Test pipetting.""" @@ -279,64 +285,59 @@ def test_single_tip_pickup_usage() -> None: well_position = f"{row}{col}" pipette_96_channel.pick_up_tip(tip_rack_2) - pipette_96_channel.aspirate(5, source_reservoir[well_position]) - pipette_96_channel.touch_tip() + pipette_96_channel.aspirate(45, source_reservoir[well_position]) + pipette_96_channel.air_gap(5) pipette_96_channel.dispense( - 5, dest_pcr_plate[well_position].bottom(b) + 25, dest_pcr_plate[well_position].bottom(b) ) + pipette_96_channel.blow_out(location=liquid_waste["A1"]) pipette_96_channel.drop_tip() tip_count += 1 # leave this dropping in waste chute, do not use get_disposal_preference # want to test partial drop - ctx.move_labware(tip_rack_2, waste_chute, use_gripper=USING_GRIPPER) + protocol.move_labware(tip_rack_2, waste_chute, use_gripper=USING_GRIPPER) + + def test_column_tip_rack_usage() -> None: + """Column Tip Pick Up.""" + list_of_columns = list(range(1, 13)) + pipette_96_channel.configure_nozzle_layout( + style=COLUMN, start="A12", tip_racks=[tip_rack_3] + ) + protocol.comment("------------------------------") + protocol.comment(f"channels {pipette_96_channel.active_channels}") + protocol.move_labware(tip_rack_3, "C3", use_gripper=USING_GRIPPER) + for well in list_of_columns: + tiprack_well = "A" + str(well) + well_name = "A" + str(well) + pipette_96_channel.liquid_presence_detection = True + pipette_96_channel.pick_up_tip(tip_rack_3[tiprack_well]) + pipette_96_channel.aspirate(45, source_reservoir[well_name]) + pipette_96_channel.liquid_presence_detection = False + pipette_96_channel.air_gap(5) + pipette_96_channel.dispense(25, dest_pcr_plate[tiprack_well].bottom(b)) + pipette_96_channel.blow_out(location=liquid_waste["A1"]) + pipette_96_channel.drop_tip() + protocol.move_labware(tip_rack_3, waste_chute, use_gripper=USING_GRIPPER) def test_full_tip_rack_usage() -> None: """Full Tip Pick Up.""" - pipette_96_channel.configure_nozzle_layout(style=ALL, start="A1") + pipette_96_channel.configure_nozzle_layout( + style=ALL, tip_racks=[tip_rack_1] + ) + protocol.comment(f"channels {pipette_96_channel.active_channels}") pipette_96_channel.liquid_presence_detection = True - pipette_96_channel.pick_up_tip(tip_rack_1["A1"]) - - pipette_96_channel.aspirate(5, source_reservoir["A1"]) - pipette_96_channel.touch_tip() - + pipette_96_channel.pick_up_tip() + pipette_96_channel.aspirate(45, source_reservoir["A1"]) pipette_96_channel.liquid_presence_detection = False - pipette_96_channel.air_gap(height=30) - pipette_96_channel.blow_out(waste_chute) - - pipette_96_channel.aspirate(5, source_reservoir["A1"]) - pipette_96_channel.touch_tip() - - pipette_96_channel.air_gap(height=30) - pipette_96_channel.blow_out() - - pipette_96_channel.aspirate(10, source_reservoir["A1"]) - pipette_96_channel.touch_tip() - - pipette_96_channel.dispense(10, dest_pcr_plate["A1"].bottom(b)) - pipette_96_channel.mix(repetitions=5, volume=15) + pipette_96_channel.air_gap(5) + pipette_96_channel.dispense(25, dest_pcr_plate["A1"].bottom(b)) + pipette_96_channel.blow_out(location=liquid_waste["A1"]) pipette_96_channel.return_tip() - - ctx.move_labware(tip_rack_1, waste_chute, use_gripper=USING_GRIPPER) - ctx.move_labware(tip_rack_3, tip_rack_adapter, use_gripper=USING_GRIPPER) - - pipette_96_channel.pick_up_tip(tip_rack_3["A1"]) - pipette_96_channel.transfer( - volume=10, - source=source_reservoir["A1"], - dest=dest_pcr_plate["A1"], - new_tip="never", - touch_tip=True, - blow_out=True, - blowout_location="trash", - mix_before=(3, 5), - mix_after=(1, 5), - ) - pipette_96_channel.return_tip() - - ctx.move_labware(tip_rack_3, waste_chute, use_gripper=USING_GRIPPER) + pipette_96_channel.reset_tipracks() test_single_tip_pickup_usage() + test_column_tip_rack_usage() test_full_tip_rack_usage() def test_module_usage(unused_lids: List[Labware], used_lids: List[Labware]) -> None: @@ -351,14 +352,14 @@ def test_thermocycler( unused_lids, used_lids, ) = helpers.use_disposable_lid_with_tc( - ctx, unused_lids, used_lids, dest_pcr_plate, thermocycler + protocol, unused_lids, used_lids, dest_pcr_plate, thermocycler ) thermocycler.set_block_temperature(4) thermocycler.set_lid_temperature(105) # Close lid thermocycler.close_lid() helpers.perform_pcr( - ctx, + protocol, thermocycler, initial_denature_time_sec=45, denaturation_time_sec=30, @@ -374,9 +375,9 @@ def test_thermocycler( thermocycler.open_lid() if disposable_lid: if len(used_lids) <= 1: - ctx.move_labware(lid_on_plate, "B3", use_gripper=True) + protocol.move_labware(lid_on_plate, waste_chute, use_gripper=True) else: - ctx.move_labware(lid_on_plate, used_lids[-2], use_gripper=True) + protocol.move_labware(lid_on_plate, used_lids[-2], use_gripper=True) thermocycler.deactivate() def test_h_s() -> None: @@ -397,16 +398,21 @@ def test_temperature_module() -> None: temperature_module.set_temperature(10) temperature_module.deactivate() - def test_mag() -> None: - """Tests magnetic block.""" - pass - test_thermocycler(unused_lids, used_lids) test_h_s() test_temperature_module() - test_mag() test_pipetting() test_gripper_moves() test_module_usage(unused_lids, used_lids) test_manual_moves() + protocol.move_labware(source_reservoir, "C2", use_gripper=True) + helpers.clean_up_plates( + pipette_96_channel, [dest_pcr_plate, source_reservoir], liquid_waste["A1"], 50 + ) + pipette_96_channel.reset_tipracks() + helpers.find_liquid_height_of_all_wells( + protocol, pipette_96_channel, [liquid_waste["A1"]] + ) + if deactivate_modules_bool: + helpers.deactivate_modules(protocol) diff --git a/abr-testing/abr_testing/protocols/active_protocols/6_Omega_HDQ_DNA_Cells-Flex_96_channel.py b/abr-testing/abr_testing/protocols/active_protocols/6_Omega_HDQ_DNA_Cells-Flex_96_channel.py index 89f643729fb..cc2103d2555 100644 --- a/abr-testing/abr_testing/protocols/active_protocols/6_Omega_HDQ_DNA_Cells-Flex_96_channel.py +++ b/abr-testing/abr_testing/protocols/active_protocols/6_Omega_HDQ_DNA_Cells-Flex_96_channel.py @@ -29,19 +29,28 @@ def add_parameters(parameters: ParameterContext) -> None: """Parameters.""" helpers.create_dot_bottom_parameter(parameters) + helpers.create_deactivate_modules_parameter(parameters) + parameters.add_int( + variable_name="number_of_runs", + display_name="Number of Runs", + default=2, + minimum=1, + maximum=10, + ) # Start protocol def run(ctx: ProtocolContext) -> None: """Protocol.""" dot_bottom = ctx.params.dot_bottom # type: ignore[attr-defined] - + deactivate_modules = ctx.params.deactivate_modules # type: ignore[attr-defined] + number_of_runs = ctx.params.number_of_runs # type: ignore[attr-defined] dry_run = False tip_mixing = False wash_vol = 600.0 AL_vol = 230.0 - bind_vol = 320.0 + bind_vol = 300.0 sample_vol = 180.0 elution_vol = 100.0 @@ -211,74 +220,43 @@ def bead_mix(vol: float, plate: Well, reps: int = 5) -> None: pip.flow_rate.aspirate = 150 pip.flow_rate.dispense = 200 - # Start Protocol - temp.set_temperature(inc_temp) - # Transfer and mix lysis - pip.pick_up_tip(tips) - pip.aspirate(AL_total_vol, lysis_res) - pip.dispense(AL_total_vol, samples_m) - resuspend_pellet(400, samples_m, reps=4 if not dry_run else 1) - if not tip_mixing: - pip.return_tip() - - # Mix, then heat - ctx.comment("Lysis Mixing") - helpers.set_hs_speed(ctx, h_s, 1800, 10, False) - if not dry_run: - h_s.set_and_wait_for_temperature(55) - ctx.delay( - minutes=10 if not dry_run else 0.25, - msg="Please allow another 10 minutes of 55C incubation to complete lysis.", - ) - h_s.deactivate_shaker() - - # Transfer and mix bind&beads - pip.pick_up_tip(tips) - bead_mix(binding_buffer_vol, bind_res, reps=4 if not dry_run else 1) - pip.aspirate(binding_buffer_vol, bind_res) - pip.dispense(binding_buffer_vol, samples_m) - bead_mix(binding_buffer_vol + starting_vol, samples_m, reps=4 if not dry_run else 1) - if not tip_mixing: - pip.return_tip() - pip.home() - - # Shake for binding incubation - ctx.comment("Binding incubation") - helpers.set_hs_speed(ctx, h_s, 1800, 10, True) - - # Transfer plate to magnet - helpers.move_labware_from_hs_to_destination(ctx, sample_plate, h_s, magblock) - - ctx.delay( - minutes=settling_time, - msg="Please wait " + str(settling_time) + " minute(s) for beads to pellet.", - ) + def protocol() -> None: + # Start Protocol + temp.set_temperature(inc_temp) + # Transfer and mix lysis + pip.pick_up_tip(tips) + pip.aspirate(AL_total_vol, lysis_res) + pip.dispense(AL_total_vol, samples_m) + resuspend_pellet(200, samples_m, reps=4 if not dry_run else 1) + if not tip_mixing: + pip.return_tip() - # Remove Supernatant and move off magnet - pip.pick_up_tip(tips) - pip.aspirate(1000, samples_m.bottom(dot_bottom)) - pip.dispense(1000, waste) - if starting_vol + binding_buffer_vol > 1000: - pip.aspirate(1000, samples_m.bottom(dot_bottom)) - pip.dispense(1000, waste) - pip.return_tip() - - # Transfer plate from magnet to H/S - helpers.move_labware_to_hs(ctx, sample_plate, h_s, h_s_adapter) - - # Washes - for i in range(num_washes if not dry_run else 1): - if i == 0 or i == 1: - wash_res = wash1_res - else: - wash_res = wash2_res + # Mix, then heat + ctx.comment("Lysis Mixing") + helpers.set_hs_speed(ctx, h_s, 1800, 10, False) + if not dry_run: + h_s.set_and_wait_for_temperature(55) + ctx.delay( + minutes=10 if not dry_run else 0.25, + msg="Please allow another 10 minutes of 55C incubation to complete lysis.", + ) + h_s.deactivate_shaker() + # Transfer and mix bind&beads pip.pick_up_tip(tips) - pip.aspirate(wash_vol, wash_res) - pip.dispense(wash_vol, samples_m) + bead_mix(binding_buffer_vol, bind_res, reps=4 if not dry_run else 1) + pip.aspirate(binding_buffer_vol, bind_res) + pip.dispense(binding_buffer_vol, samples_m) + bead_mix( + binding_buffer_vol + starting_vol, samples_m, reps=4 if not dry_run else 1 + ) if not tip_mixing: pip.return_tip() - helpers.set_hs_speed(ctx, h_s, 1800, 5, True) + pip.home() + + # Shake for binding incubation + ctx.comment("Binding incubation") + helpers.set_hs_speed(ctx, h_s, 1800, 10, True) # Transfer plate to magnet helpers.move_labware_from_hs_to_destination(ctx, sample_plate, h_s, magblock) @@ -290,62 +268,161 @@ def bead_mix(vol: float, plate: Well, reps: int = 5) -> None: # Remove Supernatant and move off magnet pip.pick_up_tip(tips) - pip.aspirate(1000, samples_m.bottom(dot_bottom)) - pip.dispense(1000, bind_res.top()) - if wash_vol > 1000: - pip.aspirate(1000, samples_m.bottom(dot_bottom)) - pip.dispense(1000, bind_res.top()) + pip.aspirate(550, samples_m.bottom(dot_bottom)) + pip.dispense(550, waste) + if starting_vol + binding_buffer_vol > 1000: + pip.aspirate(550, samples_m.bottom(dot_bottom)) + pip.dispense(550, waste) pip.return_tip() # Transfer plate from magnet to H/S helpers.move_labware_to_hs(ctx, sample_plate, h_s, h_s_adapter) - # Dry beads - if dry_run: - drybeads = 0.5 - else: - drybeads = 10 - # Number of minutes you want to dry for - for beaddry in np.arange(drybeads, 0, -0.5): + # Washes + for i in range(num_washes if not dry_run else 1): + if i == 0 or i == 1: + wash_res = wash1_res + else: + wash_res = wash2_res + + pip.pick_up_tip(tips) + pip.aspirate(wash_vol, wash_res) + pip.dispense(wash_vol, samples_m) + if not tip_mixing: + pip.return_tip() + helpers.set_hs_speed(ctx, h_s, 1800, 5, True) + + # Transfer plate to magnet + helpers.move_labware_from_hs_to_destination( + ctx, sample_plate, h_s, magblock + ) + + ctx.delay( + minutes=settling_time, + msg="Please wait " + + str(settling_time) + + " minute(s) for beads to pellet.", + ) + + # Remove Supernatant and move off magnet + pip.pick_up_tip(tips) + pip.aspirate(473, samples_m.bottom(dot_bottom)) + pip.dispense(473, bind_res.top()) + if wash_vol > 1000: + pip.aspirate(473, samples_m.bottom(dot_bottom)) + pip.dispense(473, bind_res.top()) + pip.return_tip() + + # Transfer plate from magnet to H/S + helpers.move_labware_to_hs(ctx, sample_plate, h_s, h_s_adapter) + + # Dry beads + if dry_run: + drybeads = 0.5 + else: + drybeads = 10 + # Number of minutes you want to dry for + for beaddry in np.arange(drybeads, 0, -0.5): + ctx.delay( + minutes=0.5, + msg="There are " + str(beaddry) + " minutes left in the drying step.", + ) + + # Elution + pip.pick_up_tip(tips1) + pip.aspirate(elution_vol, elution_res) + pip.dispense(elution_vol, samples_m) + resuspend_pellet(elution_vol, samples_m, reps=3 if not dry_run else 1) + if not tip_mixing: + pip.return_tip() + pip.home() + + helpers.set_hs_speed(ctx, h_s, 2000, 5, True) + + # Transfer plate to magnet + helpers.move_labware_from_hs_to_destination(ctx, sample_plate, h_s, magblock) + ctx.delay( - minutes=0.5, - msg="There are " + str(beaddry) + " minutes left in the drying step.", + minutes=settling_time, + msg="Please wait " + str(settling_time) + " minute(s) for beads to pellet.", ) - # Elution - pip.pick_up_tip(tips1) - pip.aspirate(elution_vol, elution_res) - pip.dispense(elution_vol, samples_m) - resuspend_pellet(elution_vol, samples_m, reps=3 if not dry_run else 1) - if not tip_mixing: + pip.pick_up_tip(tips1) + pip.aspirate(elution_vol, samples_m) + pip.dispense(elution_vol, elutionplate.wells()[0]) pip.return_tip() - pip.home() - - helpers.set_hs_speed(ctx, h_s, 2000, 5, True) - # Transfer plate to magnet - helpers.move_labware_from_hs_to_destination(ctx, sample_plate, h_s, magblock) + pip.home() + pip.reset_tipracks() + + # Empty Plates + pip.pick_up_tip() + pip.aspirate(500, samples_m) + pip.dispense(500, liquid_waste["A1"].top()) + pip.aspirate(500, wash1_res) + pip.dispense(500, liquid_waste["A1"].top()) + pip.aspirate(500, wash2_res) + pip.dispense(500, liquid_waste["A1"].top()) + pip.return_tip() + helpers.find_liquid_height_of_all_wells(ctx, pip, [liquid_waste["A1"]]) + helpers.move_labware_to_hs(ctx, sample_plate, h_s, h_s_adapter) - ctx.delay( - minutes=settling_time, - msg="Please wait " + str(settling_time) + " minute(s) for beads to pellet.", - ) + def setup() -> None: + pip.pick_up_tip() + pip.transfer( + volume=250, + source=liquid_waste["A1"].bottom(z=2), + dest=lysis_reservoir["A1"], + blow_out=True, + blowout_location="source well", + new_tip="never", + trash=False, + ) + pip.transfer( + 1700, + liquid_waste["A1"].bottom(z=2), + wash1_reservoir["A1"], + blow_out=True, + blowout_location="source well", + new_tip="never", + trash=False, + ) + pip.transfer( + 1100, + bind_reservoir["A1"].bottom(z=2), + wash2_reservoir["A1"], + blow_out=True, + blowout_location="source well", + new_tip="never", + trash=False, + ) + pip.transfer( + 100, + liquid_waste["A1"].bottom(z=2), + sample_plate["A1"], + blow_out=True, + blowout_location="source well", + new_tip="never", + trash=False, + ) + pip.return_tip() - pip.pick_up_tip(tips1) - pip.aspirate(elution_vol, samples_m) - pip.dispense(elution_vol, elutionplate.wells()[0]) - pip.return_tip() - - pip.home() - pip.reset_tipracks() - - # Empty Plates - pip.pick_up_tip() - pip.aspirate(1000, samples_m) - pip.dispense(1000, liquid_waste["A1"].top()) - pip.aspirate(1000, wash1_res) - pip.dispense(1000, liquid_waste["A1"].top()) - pip.aspirate(1000, wash2_res) - pip.dispense(1000, liquid_waste["A1"].top()) - pip.return_tip() - helpers.find_liquid_height_of_all_wells(ctx, pip, [liquid_waste["A1"]]) + def clean() -> None: + plates_to_clean = [ + sample_plate, + elutionplate, + wash2_reservoir, + wash1_reservoir, + liquid_waste, + ] + helpers.clean_up_plates(pip, plates_to_clean, liquid_waste["A1"], 1000) + + for i in range(number_of_runs): + protocol() + pip.reset_tipracks() + if i < number_of_runs - 1: + setup() + pip.reset_tipracks() + clean() + if deactivate_modules: + helpers.deactivate_modules(ctx) diff --git a/abr-testing/abr_testing/protocols/active_protocols/7_HDQ_DNA_Bacteria_Flex.py b/abr-testing/abr_testing/protocols/active_protocols/7_HDQ_DNA_Bacteria_Flex.py index aa33079f553..4350888b0d6 100644 --- a/abr-testing/abr_testing/protocols/active_protocols/7_HDQ_DNA_Bacteria_Flex.py +++ b/abr-testing/abr_testing/protocols/active_protocols/7_HDQ_DNA_Bacteria_Flex.py @@ -22,7 +22,7 @@ } requirements = { - "robotType": "OT-3", + "robotType": "Flex", "apiLevel": "2.21", } """ @@ -57,18 +57,22 @@ def add_parameters(parameters: ParameterContext) -> None: helpers.create_single_pipette_mount_parameter(parameters) helpers.create_hs_speed_parameter(parameters) helpers.create_dot_bottom_parameter(parameters) + helpers.create_deactivate_modules_parameter(parameters) -def run(ctx: ProtocolContext) -> None: +def run(protocol: ProtocolContext) -> None: """Protocol.""" - heater_shaker_speed = ctx.params.heater_shaker_speed # type: ignore[attr-defined] - mount = ctx.params.pipette_mount # type: ignore[attr-defined] - dot_bottom = ctx.params.dot_bottom # type: ignore[attr-defined] + heater_shaker_speed = protocol.params.heater_shaker_speed # type: ignore[attr-defined] + mount = protocol.params.pipette_mount # type: ignore[attr-defined] + dot_bottom = protocol.params.dot_bottom # type: ignore[attr-defined] + deactivate_modules_bool = protocol.params.deactivate_modules # type: ignore[attr-defined] + helpers.comment_protocol_version(protocol, "01") + dry_run = False TIP_TRASH = False res_type = "nest_12_reservoir_22ml" - num_samples = 8 + num_samples = 96 wash1_vol = 600.0 wash2_vol = 600.0 wash3_vol = 600.0 @@ -95,37 +99,48 @@ def run(ctx: ProtocolContext) -> None: starting_vol = AL_vol + sample_vol binding_buffer_vol = bind_vol + bead_vol - ctx.load_trash_bin("A3") - h_s: HeaterShakerContext = ctx.load_module(helpers.hs_str, "D1") # type: ignore[assignment] + protocol.load_trash_bin("A3") + h_s: HeaterShakerContext = protocol.load_module( + helpers.hs_str, "D1" + ) # type: ignore[assignment] sample_plate, h_s_adapter = helpers.load_hs_adapter_and_labware( deepwell_type, h_s, "Sample Plate" ) h_s.close_labware_latch() - temp: TemperatureModuleContext = ctx.load_module( + temp: TemperatureModuleContext = protocol.load_module( helpers.temp_str, "D3" ) # type: ignore[assignment] elutionplate, temp_adapter = helpers.load_temp_adapter_and_labware( "armadillo_96_wellplate_200ul_pcr_full_skirt", temp, "Elution Plate" ) - magnetic_block: MagneticBlockContext = ctx.load_module( + magnetic_block: MagneticBlockContext = protocol.load_module( helpers.mag_str, "C1" ) # type: ignore[assignment] - waste_reservoir = ctx.load_labware("nest_1_reservoir_195ml", "B3", "Liquid Waste") + waste_reservoir = protocol.load_labware( + "nest_1_reservoir_195ml", "B3", "Liquid Waste" + ) waste = waste_reservoir.wells()[0].top() - res1 = ctx.load_labware(res_type, "D2", "Reagent Reservoir 1") + res1 = protocol.load_labware(res_type, "D2", "Reagent Reservoir 1") num_cols = math.ceil(num_samples / 8) - # Load tips and combine all similar boxes - tips1000 = ctx.load_labware("opentrons_flex_96_tiprack_1000ul", "A1", "Tips 1") - tips1001 = ctx.load_labware("opentrons_flex_96_tiprack_1000ul", "A2", "Tips 2") - tips1002 = ctx.load_labware("opentrons_flex_96_tiprack_1000ul", "B1", "Tips 3") - tips = [*tips1000.wells()[num_samples:96], *tips1001.wells(), *tips1002.wells()] + tips1000 = protocol.load_labware("opentrons_flex_96_tiprack_1000ul", "A1", "Tips 1") + tips1001 = protocol.load_labware("opentrons_flex_96_tiprack_1000ul", "A2", "Tips 2") + tips1002 = protocol.load_labware("opentrons_flex_96_tiprack_1000ul", "B1", "Tips 3") + tips1003 = protocol.load_labware("opentrons_flex_96_tiprack_1000ul", "B2", "Tips 4") + tips1004 = protocol.load_labware("opentrons_flex_96_tiprack_1000ul", "C2", "Tips 5") + + tips = [ + *tips1000.wells()[num_samples:96], + *tips1001.wells(), + *tips1002.wells(), + *tips1003.wells(), + ] tips_sn = tips1000.wells()[:num_samples] # load instruments - m1000 = ctx.load_instrument( - "flex_8channel_1000", mount, tip_racks=[tips1000, tips1001, tips1002] + m1000 = protocol.load_instrument( + "flex_8channel_1000", mount, tip_racks=[tips1000, tips1001, tips1002, tips1003] ) """ @@ -158,7 +173,7 @@ def run(ctx: ProtocolContext) -> None: m1000.flow_rate.aspirate = 300 m1000.flow_rate.dispense = 300 m1000.flow_rate.blow_out = 300 - helpers.find_liquid_height_of_loaded_liquids(ctx, liquid_vols_and_wells, m1000) + helpers.find_liquid_height_of_loaded_liquids(protocol, liquid_vols_and_wells, m1000) def tiptrack(tipbox: List[Well]) -> None: """Track Tips.""" @@ -167,14 +182,15 @@ def tiptrack(tipbox: List[Well]) -> None: if tipbox == tips: m1000.pick_up_tip(tipbox[int(tip1k)]) tip1k = tip1k + 8 + if tip1k >= len(tipbox): + tip1k = 0 drop_count = drop_count + 8 if drop_count >= 150: drop_count = 0 - ctx.pause("Empty Waste Bin.") def remove_supernatant(vol: float) -> None: """Remove supernatants.""" - ctx.comment("-----Removing Supernatant-----") + protocol.comment("-----Removing Supernatant-----") m1000.flow_rate.aspirate = 150 num_trans = math.ceil(vol / 980) vol_per_trans = vol / num_trans @@ -192,7 +208,7 @@ def remove_supernatant(vol: float) -> None: m1000.air_gap(20) m1000.drop_tip(tips_sn[8 * i]) if TIP_TRASH else m1000.return_tip() m1000.flow_rate.aspirate = 300 - helpers.move_labware_to_hs(ctx, sample_plate, h_s, h_s_adapter) + helpers.move_labware_to_hs(protocol, sample_plate, h_s, h_s_adapter) def bead_mixing( well: Well, pip: InstrumentContext, mvol: float, reps: int = 8 @@ -284,7 +300,7 @@ def mixing(well: Well, pip: InstrumentContext, mvol: float, reps: int = 8) -> No def A_lysis(vol: float, source: Well) -> None: """A Lysis.""" - ctx.comment("-----Mixing then transferring AL buffer-----") + protocol.comment("-----Mixing then transferring AL buffer-----") num_transfers = math.ceil(vol / 980) tiptrack(tips) for i in range(num_cols): @@ -303,7 +319,6 @@ def A_lysis(vol: float, source: Well) -> None: m1000.require_liquid_presence(src) m1000.aspirate(tvol, src.bottom(1)) m1000.dispense(tvol, src.bottom(4)) - m1000.require_liquid_presence(src) m1000.aspirate(tvol, src.bottom(height)) m1000.air_gap(10) m1000.dispense(m1000.current_volume, samples_m[i].top()) @@ -318,12 +333,12 @@ def A_lysis(vol: float, source: Well) -> None: m1000.air_gap(20) m1000.drop_tip() if TIP_TRASH else m1000.return_tip() - ctx.comment("-----Mixing then Heating AL and Sample-----") + protocol.comment("-----Mixing then Heating AL and Sample-----") - helpers.set_hs_speed(ctx, h_s, heater_shaker_speed, A_lysis_time_1, False) + helpers.set_hs_speed(protocol, h_s, heater_shaker_speed, A_lysis_time_1, False) if not dry_run: h_s.set_and_wait_for_temperature(55) - ctx.delay( + protocol.delay( minutes=A_lysis_time_2, msg="Incubating at 55C " + str(heater_shaker_speed) @@ -347,17 +362,17 @@ def bind(vol: float) -> None: supernatant to the final clean elutions PCR plate. """ - ctx.comment("-----Beginning Bind Steps-----") + protocol.comment("-----Beginning Bind Steps-----") tiptrack(tips) for i, well in enumerate(samples_m): num_trans = math.ceil(vol / 980) vol_per_trans = vol / num_trans - source = binding_buffer[i // 3] + source = binding_buffer[i // 7] if i == 0: reps = 6 if not dry_run else 1 else: reps = 1 - ctx.comment("-----Mixing Beads in Reservoir-----") + protocol.comment("-----Mixing Beads in Reservoir-----") bead_mixing(source, m1000, vol_per_trans, reps=reps if not dry_run else 1) # Transfer beads and binding from source to H-S plate for t in range(num_trans): @@ -370,7 +385,7 @@ def bind(vol: float) -> None: if t < num_trans - 1: m1000.air_gap(20) - ctx.comment("-----Mixing Beads in Plate-----") + protocol.comment("-----Mixing Beads in Plate-----") for i in range(num_cols): if i != 0: tiptrack(tips) @@ -379,19 +394,19 @@ def bind(vol: float) -> None: ) m1000.drop_tip() if TIP_TRASH else m1000.return_tip() - ctx.comment("-----Incubating Beads and Bind on H-S-----") + protocol.comment("-----Incubating Beads and Bind on H-S-----") speed_val = heater_shaker_speed * 0.9 - helpers.set_hs_speed(ctx, h_s, speed_val, bind_time, True) + helpers.set_hs_speed(protocol, h_s, speed_val, bind_time, True) # Transfer from H-S plate to Magdeck plate helpers.move_labware_from_hs_to_destination( - ctx, sample_plate, h_s, magnetic_block + protocol, sample_plate, h_s, magnetic_block ) for bindi in np.arange( settling_time + 1, 0, -0.5 ): # Settling time delay with countdown timer - ctx.delay( + protocol.delay( minutes=0.5, msg="There are " + str(bindi) + " minutes left in the incubation.", ) @@ -410,29 +425,29 @@ def wash(vol: float, source: List[Well]) -> None: if source == wash3: whichwash = 3 - ctx.comment("-----Beginning Wash #" + str(whichwash) + "-----") + protocol.comment("-----Beginning Wash #" + str(whichwash) + "-----") num_trans = math.ceil(vol / 980) vol_per_trans = vol / num_trans tiptrack(tips) for i, m in enumerate(samples_m): - src = source[i // 2] + src = source[i // 4] for n in range(num_trans): if m1000.current_volume > 0: m1000.dispense(m1000.current_volume, src.top()) m1000.transfer(vol_per_trans, src, m.top(), air_gap=20, new_tip="never") m1000.drop_tip() if TIP_TRASH else m1000.return_tip() - helpers.set_hs_speed(ctx, h_s, heater_shaker_speed, elute_wash_time, True) + helpers.set_hs_speed(protocol, h_s, heater_shaker_speed, elute_wash_time, True) helpers.move_labware_from_hs_to_destination( - ctx, sample_plate, h_s, magnetic_block + protocol, sample_plate, h_s, magnetic_block ) for washi in np.arange( settling_time, 0, -0.5 ): # settling time timer for washes - ctx.delay( + protocol.delay( minutes=0.5, msg="There are " + str(washi) @@ -445,7 +460,7 @@ def wash(vol: float, source: List[Well]) -> None: def elute(vol: float) -> None: """Elution Function.""" - ctx.comment("-----Beginning Elution Steps-----") + protocol.comment("-----Beginning Elution Steps-----") tiptrack(tips) for i, (m, e) in enumerate(zip(samples_m, elution_samples_m)): m1000.flow_rate.aspirate = 25 @@ -457,15 +472,15 @@ def elute(vol: float) -> None: h_s.set_and_wait_for_shake_speed(heater_shaker_speed * 1.1) speed_val = heater_shaker_speed * 1.1 - helpers.set_hs_speed(ctx, h_s, speed_val, elute_wash_time, True) + helpers.set_hs_speed(protocol, h_s, speed_val, elute_wash_time, True) # Transfer back to magnet helpers.move_labware_from_hs_to_destination( - ctx, sample_plate, h_s, magnetic_block + protocol, sample_plate, h_s, magnetic_block ) for elutei in np.arange(settling_time, 0, -0.5): - ctx.delay( + protocol.delay( minutes=0.5, msg="Incubating on MagDeck for " + str(elutei) + " more minutes.", ) @@ -495,7 +510,7 @@ def elute(vol: float) -> None: else: drybeads = 0.5 for beaddry in np.arange(drybeads, 0, -0.5): - ctx.delay( + protocol.delay( minutes=0.5, msg="There are " + str(beaddry) + " minutes left in the drying step.", ) @@ -504,7 +519,9 @@ def elute(vol: float) -> None: # Probe wells end_wells_with_liquid = [ waste_reservoir.wells()[0], - res1.wells()[0], - elutionplate.wells()[0], ] - helpers.find_liquid_height_of_all_wells(ctx, m1000, end_wells_with_liquid) + m1000.tip_racks = [tips1004] + helpers.clean_up_plates(m1000, [res1, elutionplate], waste_reservoir["A1"], 1000) + helpers.find_liquid_height_of_all_wells(protocol, m1000, end_wells_with_liquid) + if deactivate_modules_bool: + helpers.deactivate_modules(protocol) diff --git a/abr-testing/abr_testing/protocols/active_protocols/8_Illumina and Plate Reader.py b/abr-testing/abr_testing/protocols/active_protocols/8_Illumina and Plate Reader.py index 4894cae41d4..3d8c664956c 100644 --- a/abr-testing/abr_testing/protocols/active_protocols/8_Illumina and Plate Reader.py +++ b/abr-testing/abr_testing/protocols/active_protocols/8_Illumina and Plate Reader.py @@ -1,5 +1,11 @@ """Illumina DNA Prep and Plate Reader Test.""" -from opentrons.protocol_api import ParameterContext, ProtocolContext, Labware +from opentrons.protocol_api import ( + ParameterContext, + ProtocolContext, + Labware, + Well, + InstrumentContext, +) from abr_testing.protocols import helpers from opentrons.protocol_api.module_contexts import ( AbsorbanceReaderContext, @@ -10,9 +16,10 @@ ) from datetime import datetime from opentrons.hardware_control.modules.types import ThermocyclerStep -from typing import List +from typing import List, Dict from opentrons import types + metadata = { "protocolName": "Illumina DNA Prep and Plate Reader Test", "author": "Platform Expansion", @@ -31,7 +38,7 @@ HYBRID_PAUSE = True # True = sets a pause on the Hybridization # PROTOCOL SETTINGS -COLUMNS = 3 # 1-3 +COLUMNS = 4 # 1-4 HYBRIDDECK = True HYBRIDTIME = 1.6 # Hours @@ -55,6 +62,8 @@ def add_parameters(parameters: ParameterContext) -> None: """Add Parameters.""" helpers.create_hs_speed_parameter(parameters) helpers.create_dot_bottom_parameter(parameters) + helpers.create_deactivate_modules_parameter(parameters) + helpers.create_plate_reader_compatible_labware_parameter(parameters) parameters.add_bool( variable_name="plate_orientation", display_name="Hellma Plate Orientation", @@ -103,6 +112,10 @@ def run(protocol: ProtocolContext) -> None: heater_shaker_speed = protocol.params.heater_shaker_speed # type: ignore[attr-defined] dot_bottom = protocol.params.dot_bottom # type: ignore[attr-defined] plate_orientation = protocol.params.plate_orientation # type: ignore[attr-defined] + deactivate_modules_bool = protocol.params.deactivate_modules # type: ignore[attr-defined] + plate_type = protocol.params.labware_plate_reader_compatible # type: ignore [attr-defined] + helpers.comment_protocol_version(protocol, "01") + plate_name_str = "hellma_plate_" + str(plate_orientation) global p200_tips global p50_tips @@ -115,7 +128,9 @@ def run(protocol: ProtocolContext) -> None: tiprack_50_2 = protocol.load_labware("opentrons_flex_96_tiprack_50ul", "A3") # MODULES + LABWARE # Reservoir - reservoir = protocol.load_labware("nest_96_wellplate_2ml_deep", "D2") + reservoir = protocol.load_labware( + "nest_96_wellplate_2ml_deep", "D2", "Liquid Waste" + ) # Heatershaker heatershaker: HeaterShakerContext = protocol.load_module( helpers.hs_str, "D1" @@ -123,6 +138,7 @@ def run(protocol: ProtocolContext) -> None: sample_plate_2 = heatershaker.load_labware( "thermoscientificnunc_96_wellplate_1300ul" ) + heatershaker.close_labware_latch() # Magnetic Block mag_block: MagneticBlockContext = protocol.load_module( helpers.mag_str, "C1" @@ -133,6 +149,7 @@ def run(protocol: ProtocolContext) -> None: sample_plate_1 = thermocycler.load_labware( "armadillo_96_wellplate_200ul_pcr_full_skirt" ) + thermocycler.open_lid() # Temperature Module temp_block: TemperatureModuleContext = protocol.load_module( helpers.temp_str, "B3" @@ -144,7 +161,7 @@ def run(protocol: ProtocolContext) -> None: plate_reader: AbsorbanceReaderContext = protocol.load_module( helpers.abs_mod_str, PLATE_READER_SLOT ) # type: ignore[assignment] - hellma_plate = protocol.load_labware("hellma_reference_plate", HELLMA_PLATE_SLOT) + hellma_plate = protocol.load_labware(plate_type, HELLMA_PLATE_SLOT) # PIPETTES p1000 = protocol.load_instrument( "flex_8channel_1000", @@ -154,6 +171,28 @@ def run(protocol: ProtocolContext) -> None: p50 = protocol.load_instrument( "flex_8channel_50", "right", tip_racks=[tiprack_50_1, tiprack_50_2] ) + + # Load liquids and probe + liquid_vols_and_wells: Dict[str, List[Dict[str, Well | List[Well] | float]]] = { + "Reagents": [ + {"well": reagent_plate.columns()[3], "volume": 75.0}, + {"well": reagent_plate.columns()[4], "volume": 15.0}, + {"well": reagent_plate.columns()[5], "volume": 20.0}, + {"well": reagent_plate.columns()[6], "volume": 65.0}, + ], + "AMPure": [{"well": reservoir.columns()[0], "volume": 120.0}], + "SMB": [{"well": reservoir.columns()[1], "volume": 750.0}], + "EtOH": [{"well": reservoir.columns()[3], "volume": 900.0}], + "RSB": [{"well": reservoir.columns()[4], "volume": 96.0}], + "Wash": [ + {"well": sample_plate_2.columns()[9], "volume": 1000.0}, + {"well": sample_plate_2.columns()[10], "volume": 1000.0}, + {"well": sample_plate_2.columns()[11], "volume": 1000.0}, + ], + "Samples": [{"well": sample_plate_1.wells(), "volume": 150.0}], + } + helpers.find_liquid_height_of_loaded_liquids(protocol, liquid_vols_and_wells, p50) + # reagent AMPure = reservoir["A1"] SMB = reservoir["A2"] @@ -165,11 +204,42 @@ def run(protocol: ProtocolContext) -> None: Liquid_trash_well_2 = reservoir["A10"] Liquid_trash_well_3 = reservoir["A11"] Liquid_trash_well_4 = reservoir["A12"] + liquid_trash_list = { + Liquid_trash_well_1: 0.0, + Liquid_trash_well_2: 0.0, + Liquid_trash_well_3: 0.0, + Liquid_trash_well_4: 0.0, + } + + def trash_liquid( + protocol: ProtocolContext, + pipette: InstrumentContext, + vol_to_trash: float, + liquid_trash_list: Dict[Well, float], + ) -> None: + """Determine which wells to use as liquid waste.""" + remaining_volume = vol_to_trash + max_capacity = 1500.0 + # Determine liquid waste location depending on current total volume + # Distribute the liquid volume sequentially + for well, current_volume in liquid_trash_list.items(): + if remaining_volume <= 0.0: + break + available_capacity = max_capacity - current_volume + if available_capacity < remaining_volume: + continue + pipette.dispense(remaining_volume, well.top()) + protocol.delay(minutes=0.1) + pipette.blow_out(well.top()) + liquid_trash_list[well] += remaining_volume + if pipette.current_volume <= 0.0: + break # Will Be distributed during the protocol - EEW_1 = sample_plate_2.wells_by_name()["A10"] - EEW_2 = sample_plate_2.wells_by_name()["A11"] - EEW_3 = sample_plate_2.wells_by_name()["A12"] + EEW_1 = sample_plate_2.wells_by_name()["A9"] + EEW_2 = sample_plate_2.wells_by_name()["A10"] + EEW_3 = sample_plate_2.wells_by_name()["A11"] + EEW_4 = sample_plate_2.wells_by_name()["A12"] NHB2 = reagent_plate.wells_by_name()["A1"] Panel = reagent_plate.wells_by_name()["A2"] @@ -206,6 +276,14 @@ def run(protocol: ProtocolContext) -> None: column_5_list = ["A7", "A8", "A9"] # Plate 2 column_6_list = ["A7", "A8", "A9"] # Plate 1 WASHES = [EEW_1, EEW_2, EEW_3] + if COLUMNS == 4: + column_1_list = ["A1", "A2", "A3", "A4"] # Plate 1 + column_2_list = ["A1", "A2", "A3", "A4"] # Plate 2 + column_3_list = ["A5", "A6", "A7", "A8"] # Plate 2 + column_4_list = ["A5", "A6", "A7", "A8"] # Plate 1 + column_5_list = ["A9", "A10", "A11", "A12"] # Plate 2 + column_6_list = ["A9", "A10", "A11", "A12"] # Plate 1 + WASHES = [EEW_1, EEW_2, EEW_3, EEW_4] def tipcheck() -> None: """Check tips.""" @@ -231,9 +309,7 @@ def tipcheck() -> None: thermocycler.set_block_temperature(58) thermocycler.set_lid_temperature(58) heatershaker.set_and_wait_for_temperature(58) - protocol.pause("Ready") heatershaker.close_labware_latch() - Liquid_trash = Liquid_trash_well_1 # Sample Plate contains 30ul of DNA @@ -409,20 +485,14 @@ def tipcheck() -> None: p1000.pick_up_tip() p1000.move_to(sample_plate_2[X].bottom(4)) p1000.aspirate(200, rate=0.25) - p1000.dispense(200, Liquid_trash.top(z=-7)) + trash_liquid(protocol, p1000, 200, liquid_trash_list) p1000.move_to(sample_plate_2[X].bottom(0.5)) p1000.aspirate(200, rate=0.25) - p1000.dispense(200, Liquid_trash.top(z=-7)) - p1000.move_to(Liquid_trash.top(z=-7)) - protocol.delay(minutes=0.1) - p1000.blow_out(Liquid_trash.top(z=-7)) - p1000.aspirate(20) + trash_liquid(protocol, p1000, 200, liquid_trash_list) p1000.return_tip() if TIP_TRASH is False else p1000.drop_tip() p200_tips += 1 tipcheck() - Liquid_trash = Liquid_trash_well_2 - # ============================================================================================ # GRIPPER MOVE sample_plate_2 FROM MAGPLATE TO heatershaker helpers.move_labware_to_hs( @@ -469,9 +539,6 @@ def tipcheck() -> None: if DRYRUN is False: protocol.delay(seconds=1 * 60) - if washcount > 2: - Liquid_trash = Liquid_trash_well_3 - protocol.comment("--> Removing Supernatant") RemoveSup = 200 for loop, X in enumerate(column_2_list): @@ -482,10 +549,7 @@ def tipcheck() -> None: p1000.move_to(sample_plate_2[X].bottom(z=0.5)) p1000.aspirate(100, rate=0.25) p1000.move_to(sample_plate_2[X].top(z=0.5)) - p1000.dispense(200, Liquid_trash.top(z=-7)) - protocol.delay(minutes=0.1) - p1000.blow_out(Liquid_trash.top(z=-7)) - p1000.aspirate(20) + trash_liquid(protocol, p1000, 200, liquid_trash_list) p1000.return_tip() if TIP_TRASH is False else p1000.drop_tip() p200_tips += 1 tipcheck() @@ -554,10 +618,7 @@ def tipcheck() -> None: p1000.move_to(sample_plate_2[X].bottom(z=0.5)) p1000.aspirate(100, rate=0.25) p1000.move_to(sample_plate_2[X].top(z=0.5)) - p1000.dispense(200, Liquid_trash.top(z=-7)) - protocol.delay(minutes=0.1) - p1000.blow_out(Liquid_trash.top(z=-7)) - p1000.aspirate(20) + trash_liquid(protocol, p1000, 200, liquid_trash_list) p1000.return_tip() if TIP_TRASH is False else p1000.drop_tip() p200_tips += 1 tipcheck() @@ -568,12 +629,7 @@ def tipcheck() -> None: p50.move_to(sample_plate_2[X].bottom(z=dot_bottom)) # original = z=0 p50.aspirate(50, rate=0.25) p50.default_speed = 200 - p50.dispense(50, Liquid_trash.top(z=-7)) - protocol.delay(minutes=0.1) - p50.blow_out() - p50.default_speed = 400 - p50.move_to(Liquid_trash.top(z=-7)) - p50.move_to(Liquid_trash.top(z=0)) + trash_liquid(protocol, p50, 50, liquid_trash_list) p50.return_tip() if TIP_TRASH is False else p50.drop_tip() p50_tips += 1 tipcheck() @@ -722,8 +778,6 @@ def tipcheck() -> None: p50_tips += 1 tipcheck() - Liquid_trash = Liquid_trash_well_4 - protocol.comment("--> ADDING AMPure (0.8x)") AMPureVol = 40.5 AMPureMixRep = 5 * 60 if DRYRUN is False else 0.1 * 60 @@ -777,12 +831,7 @@ def tipcheck() -> None: p1000.default_speed = 5 p1000.move_to(sample_plate_2[X].top(z=2)) p1000.default_speed = 200 - p1000.dispense(200, Liquid_trash.top(z=-7)) - protocol.delay(minutes=0.1) - p1000.blow_out() - p1000.default_speed = 400 - p1000.move_to(Liquid_trash.top(z=-7)) - p1000.move_to(Liquid_trash.top(z=0)) + trash_liquid(protocol, p1000, 200, liquid_trash_list) p1000.return_tip() if TIP_TRASH is False else p1000.drop_tip() p200_tips += 1 tipcheck() @@ -821,12 +870,7 @@ def tipcheck() -> None: p1000.default_speed = 5 p1000.move_to(sample_plate_2[X].top(z=2)) p1000.default_speed = 200 - p1000.dispense(200, Liquid_trash.top(z=-7)) - protocol.delay(minutes=0.1) - p1000.blow_out() - p1000.default_speed = 400 - p1000.move_to(Liquid_trash.top(z=-7)) - p1000.move_to(Liquid_trash.top(z=0)) + trash_liquid(protocol, p1000, 200, liquid_trash_list) p1000.return_tip() if TIP_TRASH is False else p1000.drop_tip() p200_tips += 1 tipcheck() @@ -842,12 +886,7 @@ def tipcheck() -> None: ) # original = (z=0) p1000.aspirate(50, rate=0.25) p1000.default_speed = 200 - p1000.dispense(50, Liquid_trash.top(z=-7)) - protocol.delay(minutes=0.1) - p1000.blow_out() - p1000.default_speed = 400 - p1000.move_to(Liquid_trash.top(z=-7)) - p1000.move_to(Liquid_trash.top(z=0)) + trash_liquid(protocol, p1000, 50, liquid_trash_list) p1000.return_tip() if TIP_TRASH is False else p1000.drop_tip() p200_tips += 1 tipcheck() @@ -945,4 +984,13 @@ def tipcheck() -> None: p1000.return_tip() if TIP_TRASH is False else p1000.drop_tip() p200_tips += 1 tipcheck() + liquids_to_probe_at_end = [ + Liquid_trash_well_1, + Liquid_trash_well_2, + Liquid_trash_well_3, + Liquid_trash_well_4, + ] + helpers.find_liquid_height_of_all_wells(protocol, p50, liquids_to_probe_at_end) plate_reader_actions(protocol, plate_reader, hellma_plate, plate_name_str) + if deactivate_modules_bool: + helpers.deactivate_modules(protocol) diff --git a/abr-testing/abr_testing/protocols/active_protocols/9_Magmax_RNA_Cells_Flex.py b/abr-testing/abr_testing/protocols/active_protocols/9_Magmax_RNA_Cells_Flex.py index 09201e58314..c44e8111490 100644 --- a/abr-testing/abr_testing/protocols/active_protocols/9_Magmax_RNA_Cells_Flex.py +++ b/abr-testing/abr_testing/protocols/active_protocols/9_Magmax_RNA_Cells_Flex.py @@ -24,7 +24,7 @@ } requirements = { - "robotType": "OT-3", + "robotType": "Flex", "apiLevel": "2.21", } """ @@ -44,15 +44,17 @@ Reservoir 1: Well 1 - 8120 ul -Well 2 - 6400 ul -Well 3-7 - 8550 ul +Well 2 - 8120 ul +Well 3 - 12800 ul +Well 4-12 - 9500 ul + """ -whichwash = 1 -sample_max = 48 -tip = 0 +whichwash = 0 +tip_pick_up = 0 drop_count = 0 waste_vol = 0 +wash_volume_tracker = 0.0 # Start protocol @@ -61,22 +63,25 @@ def add_parameters(parameters: ParameterContext) -> None: helpers.create_dot_bottom_parameter(parameters) helpers.create_single_pipette_mount_parameter(parameters) helpers.create_hs_speed_parameter(parameters) + helpers.create_deactivate_modules_parameter(parameters) -def run(ctx: ProtocolContext) -> None: +def run(protocol: ProtocolContext) -> None: """Protocol.""" dry_run = False inc_lysis = True res_type = "nest_12_reservoir_15ml" TIP_TRASH = False - num_samples = 48 + num_samples = 96 wash_vol = 150.0 lysis_vol = 140.0 stop_vol = 100.0 - elution_vol = dnase_vol = 50.0 - heater_shaker_speed = ctx.params.heater_shaker_speed # type: ignore[attr-defined] - dot_bottom = ctx.params.dot_bottom # type: ignore[attr-defined] - pipette_mount = ctx.params.pipette_mount # type: ignore[attr-defined] + elution_vol = dnase_vol = 55.0 + heater_shaker_speed = protocol.params.heater_shaker_speed # type: ignore[attr-defined] + dot_bottom = protocol.params.dot_bottom # type: ignore[attr-defined] + pipette_mount = protocol.params.pipette_mount # type: ignore[attr-defined] + deactivate_modules_bool = protocol.params.deactivate_modules # type: ignore[attr-defined] + helpers.comment_protocol_version(protocol, "01") # Protocol Parameters deepwell_type = "nest_96_wellplate_2ml_deep" @@ -93,63 +98,67 @@ def run(ctx: ProtocolContext) -> None: drybeads = elute_time = 0.25 bind_time = wash_time = dnase_time = stop_time = 0.25 bead_vol = 20.0 - ctx.load_trash_bin("A3") - h_s: HeaterShakerContext = ctx.load_module(helpers.hs_str, "D1") # type: ignore[assignment] + protocol.load_trash_bin("A3") + h_s: HeaterShakerContext = protocol.load_module( + helpers.hs_str, "D1" + ) # type: ignore[assignment] sample_plate, h_s_adapter = helpers.load_hs_adapter_and_labware( deepwell_type, h_s, "Sample Plate" ) h_s.close_labware_latch() - temp: TemperatureModuleContext = ctx.load_module( + temp: TemperatureModuleContext = protocol.load_module( helpers.temp_str, "D3" ) # type: ignore[assignment] elutionplate, temp_adapter = helpers.load_temp_adapter_and_labware( "armadillo_96_wellplate_200ul_pcr_full_skirt", temp, "Elution Plate" ) temp.set_temperature(4) - magblock: MagneticBlockContext = ctx.load_module( + magblock: MagneticBlockContext = protocol.load_module( helpers.mag_str, "C1" ) # type: ignore[assignment] - waste_reservoir = ctx.load_labware("nest_1_reservoir_195ml", "B3", "Liquid Waste") + waste_reservoir = protocol.load_labware( + "nest_1_reservoir_195ml", "B3", "Liquid Waste" + ) waste = waste_reservoir.wells()[0].top() - res1 = ctx.load_labware(res_type, "D2", "reagent reservoir 1") + res1 = protocol.load_labware(res_type, "D2", "reagent reservoir 1") num_cols = math.ceil(num_samples / 8) # Load tips and combine all similar boxes - tips200 = ctx.load_labware("opentrons_flex_96_tiprack_200ul", "A1", "Tips 1") - tips201 = ctx.load_labware("opentrons_flex_96_tiprack_200ul", "A2", "Tips 2") - tips202 = ctx.load_labware("opentrons_flex_96_tiprack_200ul", "B1", "Tips 3") - tips203 = ctx.load_labware("opentrons_flex_96_tiprack_200ul", "B2", "Tips 4") - tips = [ - *tips200.wells()[num_samples:96], - *tips201.wells(), - *tips202.wells(), - *tips203.wells(), - ] + tips200 = protocol.load_labware("opentrons_flex_96_tiprack_200ul", "A1", "Tips 1") + tips201 = protocol.load_labware("opentrons_flex_96_tiprack_200ul", "A2", "Tips 2") + tips202 = protocol.load_labware("opentrons_flex_96_tiprack_200ul", "B1", "Tips 3") + tips203 = protocol.load_labware("opentrons_flex_96_tiprack_200ul", "B2", "Tips 4") + tips204 = protocol.load_labware("opentrons_flex_96_tiprack_200ul", "C2", "Tips 5") + tips_sn = tips200.wells()[:num_samples] # load P1000M pipette - m1000 = ctx.load_instrument( + m1000 = protocol.load_instrument( "flex_8channel_1000", pipette_mount, - tip_racks=[tips200, tips201, tips202, tips203], + tip_racks=[tips200, tips201, tips202, tips203, tips204], ) # Load Liquid Locations in Reservoir elution_solution = elutionplate.rows()[0][:num_cols] - dnase1 = elutionplate.rows()[0][num_cols : 2 * num_cols] - lysis_ = res1.wells()[0] - stopreaction = res1.wells()[1] - wash1 = res1.wells()[2] - wash2 = res1.wells()[3] - wash3 = res1.wells()[4] - wash4 = res1.wells()[5] - wash5 = res1.wells()[6] - + dnase1 = elutionplate.rows()[0][:num_cols] + lysis_ = res1.wells()[0:2] + stopreaction = res1.wells()[2] + wash1 = res1.wells()[3] + wash2 = res1.wells()[4] + wash3 = res1.wells()[5] + wash4 = res1.wells()[6] + wash5 = res1.wells()[7] + wash6 = res1.wells()[8] + wash7 = res1.wells()[9] + wash8 = res1.wells()[10] + wash9 = res1.wells()[11] + all_washes = res1.wells()[3:12] """ Here is where you can define the locations of your reagents. """ samples_m = sample_plate.rows()[0][:num_cols] # 20ul beads each well - cells_m = sample_plate.rows()[0][num_cols : 2 * num_cols] + cells_m = sample_plate.rows()[0][:num_cols] elution_samples_m = elutionplate.rows()[0][:num_cols] # Do the same for color mapping beads_ = sample_plate.wells()[: (8 * num_cols)] @@ -163,36 +172,42 @@ def run(ctx: ProtocolContext) -> None: "Sample": [{"well": cells_, "volume": 0.0}], "DNAse": [{"well": dnase1_, "volume": dnase_vol}], "Elution Buffer": [{"well": elution_samps, "volume": elution_vol}], - "Lysis": [{"well": lysis_, "volume": lysis_vol}], - "Wash 1": [{"well": wash1, "volume": wash_vol}], - "Wash 2": [{"well": wash2, "volume": wash_vol}], - "Wash 3": [{"well": wash3, "volume": wash_vol}], - "Wash 4": [{"well": wash4, "volume": wash_vol}], - "Wash 5": [{"well": wash5, "volume": wash_vol}], - "Stop": [{"well": stopreaction, "volume": stop_vol}], + "Lysis": [{"well": lysis_, "volume": 8120.0}], + "Stop": [{"well": stopreaction, "volume": 6400.0}], + "Wash 1": [{"well": wash1, "volume": 9500.0}], + "Wash 2": [{"well": wash2, "volume": 9500.0}], + "Wash 3": [{"well": wash3, "volume": 9500.0}], + "Wash 4": [{"well": wash4, "volume": 9500.0}], + "Wash 5": [{"well": wash5, "volume": 9500.0}], + "Wash 6": [{"well": wash6, "volume": 9500.0}], + "Wash 7": [{"well": wash7, "volume": 9500.0}], + "Wash 8": [{"well": wash8, "volume": 9500.0}], + "Wash 9": [{"well": wash9, "volume": 9500.0}], } - helpers.find_liquid_height_of_loaded_liquids(ctx, liquid_vols_and_wells, m1000) + helpers.find_liquid_height_of_loaded_liquids(protocol, liquid_vols_and_wells, m1000) m1000.flow_rate.aspirate = 50 m1000.flow_rate.dispense = 150 m1000.flow_rate.blow_out = 300 - def tiptrack(pip: InstrumentContext, tipbox: List[Well]) -> None: + def tiptrack(pip: InstrumentContext) -> None: """Tip Track.""" - global tip + global tip_pick_up global drop_count - pip.pick_up_tip(tipbox[int(tip)]) - tip = tip + 8 + pip.pick_up_tip() + tip_pick_up += 1 drop_count = drop_count + 8 if drop_count >= 250: drop_count = 0 if TIP_TRASH: - ctx.pause("Empty Trash bin.") + protocol.pause("Empty Trash bin.") + if tip_pick_up >= 59: + pip.reset_tipracks() def remove_supernatant(vol: float) -> None: """Remove Supernatant.""" - ctx.comment("-----Removing Supernatant-----") + protocol.comment("-----Removing Supernatant-----") m1000.flow_rate.aspirate = 30 num_trans = math.ceil(vol / 180) vol_per_trans = vol / num_trans @@ -211,7 +226,7 @@ def remove_supernatant(vol: float) -> None: m1000.drop_tip(tips_sn[8 * i]) if TIP_TRASH else m1000.return_tip() m1000.flow_rate.aspirate = 300 # Move Plate From Magnet to H-S - helpers.move_labware_to_hs(ctx, sample_plate, h_s, h_s_adapter) + helpers.move_labware_to_hs(protocol, sample_plate, h_s, h_s_adapter) def bead_mixing( well: Well, pip: InstrumentContext, mvol: float, reps: int = 8 @@ -301,32 +316,39 @@ def mixing(well: Well, pip: InstrumentContext, mvol: float, reps: int = 8) -> No pip.flow_rate.aspirate = 300 pip.flow_rate.dispense = 300 - def lysis(vol: float, source: Well) -> None: + def lysis(vol: float, source: List[Well]) -> None: """Lysis Steps.""" - ctx.comment("-----Beginning lysis steps-----") + tvol_total = 0.0 + protocol.comment("-----Beginning lysis steps-----") num_transfers = math.ceil(vol / 180) - tiptrack(m1000, tips) + tiptrack(m1000) + src = source[0] for i in range(num_cols): - src = source tvol = vol / num_transfers for t in range(num_transfers): m1000.require_liquid_presence(src) m1000.aspirate(tvol, src.bottom(1)) m1000.dispense(m1000.current_volume, cells_m[i].top(-3)) + tvol_total += tvol * 8 + if tvol_total > 8000.0: + protocol.comment("-----Changing to second lysis well.------") + src = source[1] + protocol.comment(f"new source {src}") + tvol_total = 0.0 # mix after adding all reagent to wells with cells for i in range(num_cols): if i != 0: - tiptrack(m1000, tips) + tiptrack(m1000) for x in range(8 if not dry_run else 1): m1000.aspirate(tvol * 0.75, cells_m[i].bottom(dot_bottom)) m1000.dispense(tvol * 0.75, cells_m[i].bottom(8)) if x == 3: - ctx.delay(minutes=0.0167) + protocol.delay(minutes=0.0167) m1000.blow_out(cells_m[i].bottom(1)) m1000.drop_tip() if TIP_TRASH else m1000.return_tip() - helpers.set_hs_speed(ctx, h_s, heater_shaker_speed, lysis_time, True) + helpers.set_hs_speed(protocol, h_s, heater_shaker_speed, lysis_time, True) def bind() -> None: """Bind. @@ -344,10 +366,10 @@ def bind() -> None: supernatant to the final clean elutions PCR plate. """ - ctx.comment("-----Beginning bind steps-----") + protocol.comment("-----Beginning bind steps-----") for i, well in enumerate(samples_m): # Transfer cells+lysis/bind to wells with beads - tiptrack(m1000, tips) + tiptrack(m1000) m1000.aspirate(185, cells_m[i].bottom(dot_bottom)) m1000.air_gap(10) m1000.dispense(m1000.current_volume, well.bottom(8)) @@ -355,15 +377,17 @@ def bind() -> None: bead_mixing(well, m1000, 130, reps=5 if not dry_run else 1) m1000.air_gap(10) m1000.drop_tip() if TIP_TRASH else m1000.return_tip() - helpers.set_hs_speed(ctx, h_s, heater_shaker_speed, bind_time, True) + helpers.set_hs_speed(protocol, h_s, heater_shaker_speed, bind_time, True) # Transfer from H-S plate to Magdeck plate - helpers.move_labware_from_hs_to_destination(ctx, sample_plate, h_s, magblock) + helpers.move_labware_from_hs_to_destination( + protocol, sample_plate, h_s, magblock + ) for bindi in np.arange( settling_time, 0, -0.5 ): # Settling time delay with countdown timer - ctx.delay( + protocol.delay( minutes=0.5, msg="There are " + str(bindi) + " minutes left in the incubation.", ) @@ -371,45 +395,43 @@ def bind() -> None: # remove initial supernatant remove_supernatant(180) - def wash(vol: float, source: Well) -> None: + def wash(vol: float, source: List[Well]) -> None: """Wash Function.""" global whichwash # Defines which wash the protocol is on to log on the app - - if source == wash1: - whichwash = 1 - if source == wash2: - whichwash = 2 - if source == wash3: - whichwash = 3 - if source == wash4: - whichwash = 4 - - ctx.comment("-----Now starting Wash #" + str(whichwash) + "-----") - - tiptrack(m1000, tips) + protocol.comment("-----Now starting Wash #" + str(whichwash) + "-----") + global wash_volume_tracker + tiptrack(m1000) num_trans = math.ceil(vol / 180) vol_per_trans = vol / num_trans for i, m in enumerate(samples_m): - src = source + src = source[whichwash] for n in range(num_trans): m1000.aspirate(vol_per_trans, src) m1000.air_gap(10) m1000.dispense(m1000.current_volume, m.top(-2)) - ctx.delay(seconds=2) + protocol.delay(seconds=2) m1000.blow_out(m.top(-2)) + wash_volume_tracker += vol_per_trans * 8 + if wash_volume_tracker > 9600: + whichwash += 1 + src = source[whichwash] + protocol.comment(f"new wash source {whichwash}") + wash_volume_tracker = 0.0 m1000.air_gap(10) m1000.drop_tip() if TIP_TRASH else m1000.return_tip() # Shake for 5 minutes to mix wash with beads - helpers.set_hs_speed(ctx, h_s, heater_shaker_speed, wash_time, True) + helpers.set_hs_speed(protocol, h_s, heater_shaker_speed, wash_time, True) # Transfer from H-S plate to Magdeck plate - helpers.move_labware_from_hs_to_destination(ctx, sample_plate, h_s, magblock) + helpers.move_labware_from_hs_to_destination( + protocol, sample_plate, h_s, magblock + ) for washi in np.arange( settling_time, 0, -0.5 ): # settling time timer for washes - ctx.delay( + protocol.delay( minutes=0.5, msg="There are " + str(washi) @@ -419,13 +441,14 @@ def wash(vol: float, source: Well) -> None: ) remove_supernatant(vol) + protocol.comment(f"final wash source {whichwash}") def dnase(vol: float, source: List[Well]) -> None: """Steps for DNAseI.""" - ctx.comment("-----DNAseI Steps Beginning-----") + protocol.comment("-----DNAseI Steps Beginning-----") num_trans = math.ceil(vol / 180) vol_per_trans = vol / num_trans - tiptrack(m1000, tips) + tiptrack(m1000) for i, m in enumerate(samples_m): src = source[i] m1000.flow_rate.aspirate = 10 @@ -442,17 +465,17 @@ def dnase(vol: float, source: List[Well]) -> None: # Is this mixing needed? \/\/\/ for i in range(num_cols): if i != 0: - tiptrack(m1000, tips) + tiptrack(m1000) mixing(samples_m[i], m1000, 45, reps=5 if not dry_run else 1) m1000.drop_tip() if TIP_TRASH else m1000.return_tip() # Shake for 10 minutes to mix DNAseI - helpers.set_hs_speed(ctx, h_s, heater_shaker_speed, dnase_time, True) + helpers.set_hs_speed(protocol, h_s, heater_shaker_speed, dnase_time, True) def stop_reaction(vol: float, source: Well) -> None: """Adding stop solution.""" - ctx.comment("-----Adding Stop Solution-----") - tiptrack(m1000, tips) + protocol.comment("-----Adding Stop Solution-----") + tiptrack(m1000) num_trans = math.ceil(vol / 180) vol_per_trans = vol / num_trans for i, m in enumerate(samples_m): @@ -467,13 +490,15 @@ def stop_reaction(vol: float, source: Well) -> None: m1000.drop_tip() if TIP_TRASH else m1000.return_tip() # Shake for 3 minutes to mix wash with beads - helpers.set_hs_speed(ctx, h_s, heater_shaker_speed, stop_time, True) + helpers.set_hs_speed(protocol, h_s, heater_shaker_speed, stop_time, True) # Transfer from H-S plate to Magdeck plate - helpers.move_labware_from_hs_to_destination(ctx, sample_plate, h_s, magblock) + helpers.move_labware_from_hs_to_destination( + protocol, sample_plate, h_s, magblock + ) for stop in np.arange(settling_time, 0, -0.5): - ctx.delay( + protocol.delay( minutes=0.5, msg="There are " + str(stop) + " minutes left in this incubation.", ) @@ -482,8 +507,8 @@ def stop_reaction(vol: float, source: Well) -> None: def elute(vol: float) -> None: """Elution.""" - ctx.comment("-----Elution Beginning-----") - tiptrack(m1000, tips) + protocol.comment("-----Elution Beginning-----") + tiptrack(m1000) m1000.flow_rate.aspirate = 10 for i, m in enumerate(samples_m): loc = m.top(-2) @@ -498,7 +523,7 @@ def elute(vol: float) -> None: # Is this mixing needed? \/\/\/ for i in range(num_cols): if i != 0: - tiptrack(m1000, tips) + tiptrack(m1000) for mixes in range(10): m1000.aspirate(elution_vol - 10, samples_m[i]) m1000.dispense(elution_vol - 10, samples_m[i].bottom(10)) @@ -510,20 +535,22 @@ def elute(vol: float) -> None: m1000.drop_tip() if TIP_TRASH else m1000.return_tip() # Shake for 3 minutes to mix wash with beads - helpers.set_hs_speed(ctx, h_s, heater_shaker_speed, elute_time, True) + helpers.set_hs_speed(protocol, h_s, heater_shaker_speed, elute_time, True) # Transfer from H-S plate to Magdeck plate - helpers.move_labware_from_hs_to_destination(ctx, sample_plate, h_s, magblock) + helpers.move_labware_from_hs_to_destination( + protocol, sample_plate, h_s, magblock + ) for elutei in np.arange(settling_time, 0, -0.5): - ctx.delay( + protocol.delay( minutes=0.5, msg="Incubating on MagDeck for " + str(elutei) + " more minutes.", ) - ctx.comment("-----Trasnferring Sample to Elution Plate-----") + protocol.comment("-----Trasnferring Sample to Elution Plate-----") for i, (m, e) in enumerate(zip(samples_m, elution_samples_m)): - tiptrack(m1000, tips) + tiptrack(m1000) loc = m.bottom(dot_bottom) m1000.transfer(vol, loc, e.bottom(5), air_gap=20, new_tip="never") m1000.blow_out(e.top(-2)) @@ -537,23 +564,27 @@ def elute(vol: float) -> None: if inc_lysis: lysis(lysis_vol, lysis_) bind() - wash(wash_vol, wash1) - wash(wash_vol, wash2) + wash(wash_vol, all_washes) + wash(wash_vol, all_washes) + wash(wash_vol, all_washes) # dnase1 treatment dnase(dnase_vol, dnase1) stop_reaction(stop_vol, stopreaction) # Resume washes - wash(wash_vol, wash3) - wash(wash_vol, wash4) - wash(wash_vol, wash5) + wash(wash_vol, all_washes) + wash(wash_vol, all_washes) + wash(wash_vol, all_washes) for beaddry in np.arange(drybeads, 0, -0.5): - ctx.delay( + protocol.delay( minutes=0.5, msg="There are " + str(beaddry) + " minutes left in the drying step.", ) elute(elution_vol) - - end_list_of_wells_to_probe = [waste_reservoir["A1"], res1["A1"]] - end_list_of_wells_to_probe.extend(elution_samples_m) - helpers.find_liquid_height_of_all_wells(ctx, m1000, end_list_of_wells_to_probe) + end_list_of_wells_to_probe = [waste_reservoir["A1"]] + helpers.clean_up_plates( + m1000, [elutionplate, sample_plate], waste_reservoir["A1"], 200 + ) + helpers.find_liquid_height_of_all_wells(protocol, m1000, end_list_of_wells_to_probe) + if deactivate_modules_bool: + helpers.deactivate_modules(protocol) diff --git a/abr-testing/abr_testing/protocols/csv_parameters/1_samplevols.csv b/abr-testing/abr_testing/protocols/csv_parameters/1_samplevols.csv new file mode 100644 index 00000000000..132b4dc70fb --- /dev/null +++ b/abr-testing/abr_testing/protocols/csv_parameters/1_samplevols.csv @@ -0,0 +1,97 @@ +Well,Dye,Diluent +A1,0,100 +B1,5,95 +C1,10,90 +D1,20,80 +E1,40,60 +F1,15,40 +G1,40,20 +H1,40,0 +A2,35,65 +B2,38,42 +C2,42,58 +D2,32,8 +E2,38,12 +F2,26,74 +G2,31,69 +H2,46,4 +A3,47,13 +B3,42,18 +C3,46,64 +D3,48,22 +E3,26,74 +F3,34,66 +G3,43,37 +H3,20,80 +A4,44,16 +B4,49,41 +C4,48,42 +D4,44,16 +E4,47,53 +F4,47,33 +G4,42,48 +H4,39,21 +A5,30,20 +B5,36,14 +C5,31,59 +D5,38,52 +E5,36,4 +F5,32,28 +G5,35,55 +H5,39,1 +A6,31,59 +B6,20,80 +C6,38,2 +D6,34,46 +E6,30,70 +F6,32,58 +G6,21,79 +H6,38,52 +A7,33,27 +B7,34,16 +C7,40,60 +D7,34,26 +E7,30,20 +F7,44,56 +G7,26,74 +H7,45,55 +A8,39,1 +B8,38,2 +C8,34,66 +D8,39,11 +E8,46,54 +F8,37,63 +G8,38,42 +H8,34,66 +A9,44,56 +B9,39,11 +C9,30,70 +D9,37,33 +E9,46,54 +F9,39,21 +G9,29,41 +H9,23,77 +A10,26,74 +B10,39,1 +C10,31,49 +D10,38,62 +E10,29,1 +F10,21,79 +G10,29,41 +H10,28,42 +A11,15,55 +B11,28,72 +C11,11,49 +D11,34,66 +E11,27,73 +F11,30,40 +G11,33,67 +H11,31,39 +A12,39,31 +B12,47,53 +C12,46,54 +D12,13,7 +E12,34,46 +F12,45,35 +G12,28,42 +H12,37,63 \ No newline at end of file diff --git a/abr-testing/abr_testing/protocols/csv_parameters/2_samplevols.csv b/abr-testing/abr_testing/protocols/csv_parameters/2_samplevols.csv index fa50562e68b..424aae072c3 100644 --- a/abr-testing/abr_testing/protocols/csv_parameters/2_samplevols.csv +++ b/abr-testing/abr_testing/protocols/csv_parameters/2_samplevols.csv @@ -6,20 +6,92 @@ D1,3,7,40,A1 E1,2,8,40,A2 F1,1,9,40,A2 G1,5,5,40,A2 -H1,3,7,40,A3 +H1,3,7,40,A2 A2,3,7,40,A3 B2,3,7,40,A3 C2,3,7,40,A3 D2,3,7,40,A3 -E2,3,7,40,A3 -F2,3,7,40,A3 -G2,3,7,40,A3 -H2,3,7,40,A3 -A3,3,7,40,A3 -B3,3,7,40,A3 -C3,3,7,45,A3 -D3,3,7,45,A3 -E3,3,5,45,A3 -F3,3,5,45,A3 +E2,3,7,40,A4 +F2,3,7,40,A4 +G2,3,7,40,A4 +H2,3,7,40,A4 +A3,3,7,40,A5 +B3,3,7,40,A5 +C3,3,7,45,A5 +D3,3,7,45,A5 +E3,3,5,45,A6 +F3,3,5,45,A6 G3,3,5,45,A6 -H3,3,4,45,A5 \ No newline at end of file +H3,3,4,45,A6 +A4,3,7,40,A1 +B4,0,10,40,A1 +C4,10,0,40,A1 +D4,3,7,40,A1 +E4,2,8,40,A2 +F4,1,9,40,A2 +G4,5,5,40,A2 +H4,3,7,40,A2 +A5,3,7,40,A3 +B5,3,7,40,A3 +C5,3,7,40,A3 +D5,3,7,40,A3 +E5,3,7,40,A4 +F5,3,7,40,A4 +G5,3,7,40,A4 +H5,3,7,40,A4 +A6,3,7,40,A5 +B6,3,7,40,A5 +C6,3,7,45,A5 +D6,3,7,45,A5 +E6,3,5,45,A6 +F6,3,5,45,A6 +G6,3,5,45,A6 +H6,3,4,45,A6 +A7,3,7,40,A1 +B7,0,10,40,A1 +C7,10,0,40,A1 +D7,3,7,40,A1 +E7,2,8,40,A2 +F7,1,9,40,A2 +G7,5,5,40,A2 +H7,3,7,40,A2 +A8,3,7,40,A3 +B8,3,7,40,A3 +C8,3,7,40,A3 +D8,3,7,40,A3 +E8,3,7,40,A4 +F8,3,7,40,A4 +G8,3,7,40,A4 +H8,3,7,40,A4 +A9,3,7,40,A5 +B9,3,7,40,A5 +C9,3,7,45,A5 +D9,3,7,45,A5 +E9,3,5,45,A6 +F9,3,5,45,A6 +G9,3,5,45,A6 +H9,3,4,45,A6 +A10,3,7,40,A1 +B10,0,10,40,A1 +C10,10,0,40,A1 +D10,3,7,40,A1 +E10,2,8,40,A2 +F10,1,9,40,A2 +G10,5,5,40,A2 +H10,3,7,40,A2 +A11,3,7,40,A3 +B11,3,7,40,A3 +C11,3,7,40,A3 +D11,3,7,40,A3 +E11,3,7,40,A4 +F11,3,7,40,A4 +G11,3,7,40,A4 +H11,3,7,40,A4 +A12,3,7,40,A5 +B12,3,7,40,A5 +C12,3,7,45,A5 +D12,3,7,45,A5 +E12,3,5,45,A6 +F12,3,5,45,A6 +G12,3,5,45,A6 +H12,3,4,45,A6 diff --git a/abr-testing/abr_testing/protocols/helpers.py b/abr-testing/abr_testing/protocols/helpers.py index 12abbfa9b3f..31a1d1a9244 100644 --- a/abr-testing/abr_testing/protocols/helpers.py +++ b/abr-testing/abr_testing/protocols/helpers.py @@ -7,14 +7,15 @@ ParameterContext, Well, ) -from typing import Tuple from opentrons.protocol_api.module_contexts import ( HeaterShakerContext, MagneticBlockContext, ThermocyclerContext, TemperatureModuleContext, + MagneticModuleContext, + AbsorbanceReaderContext, ) -from typing import List, Union, Dict +from typing import List, Union, Dict, Tuple from opentrons.hardware_control.modules.types import ThermocyclerStep from opentrons_shared_data.errors.exceptions import PipetteLiquidNotFoundError @@ -106,7 +107,62 @@ def load_temp_adapter_and_labware( return labware_on_temp_mod, temp_adapter +# FUNCTIONS FOR COMMON COMMENTS + + +def comment_protocol_version(protocol: ProtocolContext, version: str) -> None: + """Comment version number of protocol.""" + protocol.comment(f"Protocol Version: {version}") + + # FUNCTIONS FOR LOADING COMMON PARAMETERS +def create_channel_parameter(parameters: ParameterContext) -> None: + """Create pipette channel parameter.""" + parameters.add_str( + variable_name="channels", + display_name="Number of Pipette Channels", + choices=[ + {"display_name": "1 Channel", "value": "1channel"}, + {"display_name": "8 Channel", "value": "8channel"}, + ], + default="8channel", + ) + + +def create_pipette_parameters(parameters: ParameterContext) -> None: + """Create parameter for pipettes.""" + # NOTE: Place function inside def add_parameters(parameters) in protocol. + # NOTE: Copy ctx.params.left mount, ctx.params.right_mount # type: ignore[attr-defined] + # to get result + # Left Mount + parameters.add_str( + variable_name="left_mount", + display_name="Left Mount", + description="Pipette Type on Left Mount.", + choices=[ + {"display_name": "8ch 50ul", "value": "flex_8channel_50"}, + {"display_name": "8ch 1000ul", "value": "flex_8channel_1000"}, + {"display_name": "1ch 50ul", "value": "flex_1channel_50"}, + {"display_name": "1ch 1000ul", "value": "flex_1channel_1000"}, + {"display_name": "96ch 1000ul", "value": "flex_96channel_1000"}, + {"display_name": "None", "value": "none"}, + ], + default="flex_8channel_1000", + ) + # Right Mount + parameters.add_str( + variable_name="right_mount", + display_name="Right Mount", + description="Pipette Type on Right Mount.", + choices=[ + {"display_name": "8ch 50ul", "value": "flex_8channel_50"}, + {"display_name": "8ch 1000ul", "value": "flex_8channel_1000"}, + {"display_name": "1ch 50ul", "value": "flex_1channel_50"}, + {"display_name": "1ch 1000ul", "value": "flex_1channel_1000"}, + {"display_name": "None", "value": "none"}, + ], + default="none", + ) def create_single_pipette_mount_parameter(parameters: ParameterContext) -> None: @@ -163,6 +219,16 @@ def create_disposable_lid_parameter(parameters: ParameterContext) -> None: ) +def create_disposable_lid_trash_location(parameters: ParameterContext) -> None: + """Create a parameter for lid placement after use.""" + parameters.add_bool( + variable_name="trash_lid", + display_name="Trash Disposable Lid", + description="True means trash lid, false means keep on deck.", + default=True, + ) + + def create_tc_lid_deck_riser_parameter(parameters: ParameterContext) -> None: """Create parameter for tc lid deck riser.""" parameters.add_bool( @@ -184,7 +250,7 @@ def create_tip_size_parameter(parameters: ParameterContext) -> None: {"display_name": "200 µL", "value": "opentrons_flex_96_tiprack_200ul"}, {"display_name": "1000 µL", "value": "opentrons_flex_96_tiprack_1000ul"}, ], - default="opentrons_flex_96_tiprack_1000ul", + default="opentrons_flex_96_tiprack_50ul", ) @@ -224,6 +290,25 @@ def create_hs_speed_parameter(parameters: ParameterContext) -> None: ) +def create_plate_reader_compatible_labware_parameter( + parameters: ParameterContext, +) -> None: + """Create parameter for flat bottom plates compatible with plate reader.""" + parameters.add_str( + variable_name="labware_plate_reader_compatible", + display_name="Plate Reader Labware", + default="nest_96_wellplate_200ul_flat", + choices=[ + { + "display_name": "Corning_96well", + "value": "corning_96_wellplate_360ul_flat", + }, + {"display_name": "Hellma Plate", "value": "hellma_reference_plate"}, + {"display_name": "Nest_96well", "value": "nest_96_wellplate_200ul_flat"}, + ], + ) + + def create_tc_compatible_labware_parameter(parameters: ParameterContext) -> None: """Create parameter for labware type compatible with thermocycler.""" parameters.add_str( @@ -249,7 +334,33 @@ def create_tc_compatible_labware_parameter(parameters: ParameterContext) -> None ) +def create_deactivate_modules_parameter(parameters: ParameterContext) -> None: + """Create parameter for deactivating modules at the end fof run.""" + parameters.add_bool( + variable_name="deactivate_modules", + display_name="Deactivate Modules", + description="deactivate all modules at end of run", + default=True, + ) + + # FUNCTIONS FOR COMMON MODULE SEQUENCES +def deactivate_modules(protocol: ProtocolContext) -> None: + """Deactivate all loaded modules.""" + print("Deactivating Modules") + modules = protocol.loaded_modules + + if modules: + for module in modules.values(): + if isinstance(module, HeaterShakerContext): + module.deactivate_shaker() + module.deactivate_heater() + elif isinstance(module, TemperatureModuleContext): + module.deactivate() + elif isinstance(module, MagneticModuleContext): + module.disengage() + elif isinstance(module, ThermocyclerContext): + module.deactivate() def move_labware_from_hs_to_destination( @@ -314,6 +425,39 @@ def use_disposable_lid_with_tc( # FUNCTIONS FOR COMMON PIPETTE COMMAND SEQUENCES +def clean_up_plates( + pipette: InstrumentContext, + list_of_labware: List[Labware], + liquid_waste: Well, + tip_size: int, +) -> None: + """Aspirate liquid from labware and dispense into liquid waste.""" + pipette.pick_up_tip() + pipette.liquid_presence_detection = False + num_of_active_channels = pipette.active_channels + for labware in list_of_labware: + if num_of_active_channels == 8: + list_of_wells = labware.rows()[0] + elif num_of_active_channels == 1: + list_of_wells = labware.wells() + elif num_of_active_channels == 96: + list_of_wells = [labware.wells()[0]] + for well in list_of_wells: + vol_removed = 0.0 + while well.max_volume > vol_removed: + pipette.aspirate(tip_size, well) + pipette.dispense( + tip_size, + liquid_waste.top(), + ) + pipette.blow_out(liquid_waste.top()) + vol_removed += pipette.max_volume + if pipette.channels != num_of_active_channels: + pipette.drop_tip() + else: + pipette.return_tip() + + def find_liquid_height(pipette: InstrumentContext, well_to_probe: Well) -> float: """Find liquid height of well.""" try: @@ -372,6 +516,18 @@ def load_wells_with_custom_liquids( well.load_liquid(liquid, volume) +def comment_height_of_specific_labware( + protocol: ProtocolContext, labware_name: str, dict_of_labware_heights: Dict +) -> None: + """Comment height found of specific labware.""" + total_height = 0.0 + for key in dict_of_labware_heights.keys(): + if key[0] == labware_name: + height = dict_of_labware_heights[key] + total_height += height + protocol.comment(f"Liquid Waste Total Height: {total_height}") + + def find_liquid_height_of_all_wells( protocol: ProtocolContext, pipette: InstrumentContext, @@ -382,7 +538,7 @@ def find_liquid_height_of_all_wells( pipette.pick_up_tip() pip_channels = pipette.active_channels for well in wells: - labware_name = well.parent.load_name + labware_name = well.parent.name total_number_of_wells_in_plate = len(well.parent.wells()) # if pip_channels is > 1 and total_wells > 12 - only probe 1st row. if ( @@ -402,6 +558,9 @@ def find_liquid_height_of_all_wells( pipette.reset_tipracks() msg = f"result: {dict_of_labware_heights}" protocol.comment(msg=msg) + comment_height_of_specific_labware( + protocol, "Liquid Waste", dict_of_labware_heights + ) return dict_of_labware_heights @@ -423,6 +582,8 @@ def find_liquid_height_of_loaded_liquids( entry["well"] if isinstance(entry["well"], list) else [entry["well"]] ) ] + if pipette.active_channels == 96: + wells = [well for well in wells if well.display_name.split(" ")[0] == "A1"] find_liquid_height_of_all_wells(ctx, pipette, wells) return wells @@ -463,6 +624,14 @@ def load_wells_with_water( "#C0C0C0", ] +# Modules with deactivate +ModuleTypes = Union[ + TemperatureModuleContext, + ThermocyclerContext, + HeaterShakerContext, + MagneticModuleContext, + AbsorbanceReaderContext, +] # THERMOCYCLER PROFILES @@ -501,6 +670,3 @@ def perform_pcr( thermocycler.execute_profile( steps=final_extension_profile, repetitions=1, block_max_volume=50 ) - - -# TODO: Create dictionary of labware, module, and adapter. diff --git a/abr-testing/abr_testing/protocols/liquid_setups/10_ZymoBIOMICS Magbead Liquid Setup.py b/abr-testing/abr_testing/protocols/liquid_setups/10_ZymoBIOMICS Magbead Liquid Setup.py index 422102e4321..76b72b97164 100644 --- a/abr-testing/abr_testing/protocols/liquid_setups/10_ZymoBIOMICS Magbead Liquid Setup.py +++ b/abr-testing/abr_testing/protocols/liquid_setups/10_ZymoBIOMICS Magbead Liquid Setup.py @@ -13,7 +13,7 @@ requirements = { "robotType": "Flex", - "apiLevel": "2.20", + "apiLevel": "2.21", } @@ -26,14 +26,16 @@ def run(protocol: protocol_api.ProtocolContext) -> None: p1000, ) = load_common_liquid_setup_labware_and_instruments(protocol) - res1 = protocol.load_labware("nest_12_reservoir_15ml", "C3", "R1") - res2 = protocol.load_labware("nest_12_reservoir_15ml", "B3", "R2") + res1 = protocol.load_labware("nest_12_reservoir_15ml", "D3", "Reagent Reservoir 1") + res2 = protocol.load_labware("nest_12_reservoir_15ml", "C3", "Reagent Reservoir 2") + res3 = protocol.load_labware("nest_12_reservoir_15ml", "B3", "Reagent Reservoir 3") lysis_and_pk = 12320 / 8 beads_and_binding = 11875 / 8 binding2 = 13500 / 8 - wash2 = 9000 / 8 + wash2 = 9800 / 8 wash2_list = [wash2] * 12 + final_elution = 1200 / 8 # Fill up Plates # Res1 p1000.transfer( @@ -42,7 +44,10 @@ def run(protocol: protocol_api.ProtocolContext) -> None: beads_and_binding, beads_and_binding, beads_and_binding, - binding2, + beads_and_binding, + beads_and_binding, + beads_and_binding, + beads_and_binding, binding2, binding2, binding2, @@ -58,6 +63,9 @@ def run(protocol: protocol_api.ProtocolContext) -> None: res1["A6"].top(), res1["A7"].top(), res1["A8"].top(), + res1["A9"].top(), + res1["A10"].top(), + res1["A11"].top(), res1["A12"].top(), ], blow_out=True, @@ -66,10 +74,19 @@ def run(protocol: protocol_api.ProtocolContext) -> None: ) # Res2 p1000.transfer( - volume=wash2_list, - source=source_reservoir["A1"], + volume=[final_elution] + wash2_list[:11], + source=[source_reservoir["A1"]] * 12, dest=res2.wells(), blow_out=True, blowout_location="source well", trash=False, ) + # Res 3 + p1000.transfer( + volume=[wash2, wash2], + source=[source_reservoir["A1"], source_reservoir["A1"]], + dest=[res3["A1"], res3["A2"]], + blow_out=True, + blowout_location="source well", + trash=False, + ) diff --git a/abr-testing/abr_testing/protocols/liquid_setups/11_Dynabeads RIT Liquid Setup.py b/abr-testing/abr_testing/protocols/liquid_setups/11_Dynabeads RIT Liquid Setup.py index 112aec315b5..2d722d410e5 100644 --- a/abr-testing/abr_testing/protocols/liquid_setups/11_Dynabeads RIT Liquid Setup.py +++ b/abr-testing/abr_testing/protocols/liquid_setups/11_Dynabeads RIT Liquid Setup.py @@ -13,7 +13,7 @@ requirements = { "robotType": "Flex", - "apiLevel": "2.20", + "apiLevel": "2.21", } @@ -27,8 +27,11 @@ def run(protocol: protocol_api.ProtocolContext) -> None: ) = load_common_liquid_setup_labware_and_instruments(protocol) reservoir_wash = protocol.load_labware("nest_12_reservoir_15ml", "D2", "Reservoir") - sample_plate = protocol.load_labware( - "nest_96_wellplate_2ml_deep", "C3", "Sample Plate" + sample_plate1 = protocol.load_labware( + "nest_96_wellplate_2ml_deep", "C3", "Sample Plate 1" + ) + sample_plate2 = protocol.load_labware( + "nest_96_wellplate_2ml_deep", "B3", "Sample Plate 2" ) columns = [ @@ -52,10 +55,24 @@ def run(protocol: protocol_api.ProtocolContext) -> None: p1000.dispense(750, reservoir_wash[i].top()) p1000.blow_out(location=source_reservoir["A1"].top()) p1000.return_tip() + # 1 column 6000 uL + p1000.pick_up_tip() + for i in columns: + p1000.aspirate(750, source_reservoir["A1"].bottom(z=0.5)) + p1000.dispense(750, reservoir_wash[i].top()) + p1000.blow_out(location=source_reservoir["A1"].top()) + p1000.return_tip() + # Nest 96 Deep Well Plate 2 mL: 250 uL per well + p1000.pick_up_tip() + for n in columns: + p1000.aspirate(250, source_reservoir["A1"].bottom(z=0.5)) + p1000.dispense(250, sample_plate1[n].bottom(z=1)) + p1000.blow_out(location=source_reservoir["A1"].top()) + p1000.return_tip() # Nest 96 Deep Well Plate 2 mL: 250 uL per well p1000.pick_up_tip() for n in columns: p1000.aspirate(250, source_reservoir["A1"].bottom(z=0.5)) - p1000.dispense(250, sample_plate[n].bottom(z=1)) + p1000.dispense(250, sample_plate2[n].bottom(z=1)) p1000.blow_out(location=source_reservoir["A1"].top()) p1000.return_tip() diff --git a/abr-testing/abr_testing/protocols/liquid_setups/12_KAPA HyperPlus Library Prep Liquid Setup.py b/abr-testing/abr_testing/protocols/liquid_setups/12_KAPA HyperPlus Library Prep Liquid Setup.py index 2575caecf6e..688533ffd55 100644 --- a/abr-testing/abr_testing/protocols/liquid_setups/12_KAPA HyperPlus Library Prep Liquid Setup.py +++ b/abr-testing/abr_testing/protocols/liquid_setups/12_KAPA HyperPlus Library Prep Liquid Setup.py @@ -13,7 +13,7 @@ requirements = { "robotType": "Flex", - "apiLevel": "2.20", + "apiLevel": "2.21", } diff --git a/abr-testing/abr_testing/protocols/liquid_setups/1_Simple normalize long Liquid Setup.py b/abr-testing/abr_testing/protocols/liquid_setups/1_Simple normalize long Liquid Setup.py index 2d995fede39..a99bb0568cf 100644 --- a/abr-testing/abr_testing/protocols/liquid_setups/1_Simple normalize long Liquid Setup.py +++ b/abr-testing/abr_testing/protocols/liquid_setups/1_Simple normalize long Liquid Setup.py @@ -12,7 +12,7 @@ requirements = { "robotType": "Flex", - "apiLevel": "2.20", + "apiLevel": "2.21", } @@ -26,14 +26,22 @@ def run(protocol: protocol_api.ProtocolContext) -> None: ) = load_common_liquid_setup_labware_and_instruments(protocol) reservoir = protocol.load_labware("nest_12_reservoir_15ml", "D2", "Reservoir") # Transfer Liquid - vol = 5400 / 8 + vol = 6175 / 8 columns = ["A1", "A2", "A3", "A4", "A5"] for i in columns: p1000.transfer( vol, - source=source_reservoir["A1"].bottom(z=0.5), + source=source_reservoir["A1"].bottom(z=2), dest=reservoir[i].top(), blowout=True, blowout_location="source well", trash=False, ) + p1000.transfer( + 8500 / 8, + source=source_reservoir["A1"].bottom(z=2), + dest=reservoir["A6"], + blowout=True, + blowout_location="source well", + trash=False, + ) diff --git a/abr-testing/abr_testing/protocols/liquid_setups/2_BMS_PCR_protocol Liquid Setup.py b/abr-testing/abr_testing/protocols/liquid_setups/2_BMS_PCR_protocol Liquid Setup.py index a6c71b563d4..1ffefc48f19 100644 --- a/abr-testing/abr_testing/protocols/liquid_setups/2_BMS_PCR_protocol Liquid Setup.py +++ b/abr-testing/abr_testing/protocols/liquid_setups/2_BMS_PCR_protocol Liquid Setup.py @@ -7,13 +7,13 @@ metadata = { "protocolName": "DVT1ABR2 Liquids: BMS PCR Protocol", - "author": "Rhyann clarke ", + "author": "Rhyann Clarke ", "source": "Protocol Library", } requirements = { "robotType": "Flex", - "apiLevel": "2.20", + "apiLevel": "2.21", } @@ -33,9 +33,9 @@ def run(protocol: protocol_api.ProtocolContext) -> None: ) # Steps # Dispense into plate 1 - p1000.transfer(50, source_reservoir["A1"], pcr_plate_1.wells(), trash=False) + p1000.transfer(100, source_reservoir["A1"], pcr_plate_1.wells(), trash=False) # Dispense p1000.configure_nozzle_layout(protocol_api.SINGLE, start="H1", tip_racks=[tip_rack]) - p1000.transfer(1500, source_reservoir["A1"], snap_caps["B1"]) - p1000.transfer(1500, source_reservoir["A1"], snap_caps.rows()[0]) + p1000.transfer(1000, source_reservoir["A1"], snap_caps["B1"]) + p1000.transfer(1000, source_reservoir["A1"], snap_caps.rows()[0]) diff --git a/abr-testing/abr_testing/protocols/liquid_setups/3_Tartrazine Liquid Setup.py b/abr-testing/abr_testing/protocols/liquid_setups/3_Tartrazine Liquid Setup.py index 9e0b29a03ed..f0941bb398b 100644 --- a/abr-testing/abr_testing/protocols/liquid_setups/3_Tartrazine Liquid Setup.py +++ b/abr-testing/abr_testing/protocols/liquid_setups/3_Tartrazine Liquid Setup.py @@ -1,8 +1,6 @@ """Plate Filler Protocol for Tartrazine Protocol.""" from opentrons import protocol_api -from abr_testing.protocols.helpers import ( - load_common_liquid_setup_labware_and_instruments, -) +from abr_testing.protocols import helpers metadata = { "protocolName": "DVT1ABR3 Liquids: Tartrazine Protocol", @@ -12,36 +10,77 @@ requirements = { "robotType": "Flex", - "apiLevel": "2.20", + "apiLevel": "2.21", } +def add_parameters(parameters: protocol_api.ParameterContext) -> None: + """Add parameters.""" + parameters.add_int( + variable_name="number_of_plates", + display_name="Number of Plates", + default=4, + minimum=1, + maximum=4, + ) + helpers.create_channel_parameter(parameters) + + def run(protocol: protocol_api.ProtocolContext) -> None: """Protocol.""" + number_of_plates = protocol.params.number_of_plates # type: ignore [attr-defined] + channels = protocol.params.channels # type: ignore [attr-defined] # Initiate Labware ( source_reservoir, tip_rack, p1000, - ) = load_common_liquid_setup_labware_and_instruments(protocol) - reagent_tube = protocol.load_labware( - "opentrons_10_tuberack_falcon_4x50ml_6x15ml_conical", "D3", "Reagent Tube" - ) - p1000.configure_nozzle_layout( - style=protocol_api.SINGLE, start="H1", tip_racks=[tip_rack] - ) - # Transfer Liquid - p1000.transfer( - 45000, - source_reservoir["A1"], - reagent_tube["B3"].top(), - blowout=True, - blowout_location="source well", - ) - p1000.transfer( - 45000, - source_reservoir["A1"], - reagent_tube["A4"].top(), - blowout=True, - blowout_location="source well", - ) + ) = helpers.load_common_liquid_setup_labware_and_instruments(protocol) + if channels == "1channel": + reagent_tube = protocol.load_labware( + "opentrons_10_tuberack_falcon_4x50ml_6x15ml_conical", "D3", "Reagent Tube" + ) + p1000.configure_nozzle_layout( + style=protocol_api.SINGLE, start="H1", tip_racks=[tip_rack] + ) + # Transfer Liquid + p1000.transfer( + 45000, + source_reservoir["A1"], + reagent_tube["B3"].top(), + blowout=True, + blowout_location="source well", + ) + p1000.transfer( + 45000, + source_reservoir["A1"], + reagent_tube["A4"].top(), + blowout=True, + blowout_location="source well", + ) + elif channels == "8channel": + reservoir = protocol.load_labware("nest_12_reservoir_15ml", "D3", "Reservoir") + water_max_vol = reservoir["A1"].max_volume - 500 + reservoir_wells = reservoir.wells()[ + 1: + ] # Skip A1 as it's reserved for tartrazine + # NEEDED WATER + needed_water: float = ( + float(number_of_plates) * 96.0 * 250.0 + ) # loading extra as a safety factor + # CALCULATING NEEDED # OF WATER WELLS + needed_wells = round(needed_water / water_max_vol) + water_wells = [] + for i in range(needed_wells + 1): + water_wells.append(reservoir_wells[i]) + # Create lists of volumes and source that matches wells to fill + water_max_vol_list = [water_max_vol] * len(water_wells) + source_list = [source_reservoir["A1"]] * len(water_wells) + p1000.transfer( + water_max_vol_list, + source_list, + water_wells, + blowout=True, + blowout_locaiton="source", + trash=False, + ) diff --git a/abr-testing/abr_testing/protocols/liquid_setups/4_Illumina DNA Enrichment Liquid Setup.py b/abr-testing/abr_testing/protocols/liquid_setups/4_Illumina DNA Enrichment Liquid Setup.py index 18aee383ace..937c9f4dafd 100644 --- a/abr-testing/abr_testing/protocols/liquid_setups/4_Illumina DNA Enrichment Liquid Setup.py +++ b/abr-testing/abr_testing/protocols/liquid_setups/4_Illumina DNA Enrichment Liquid Setup.py @@ -12,7 +12,7 @@ requirements = { "robotType": "Flex", - "apiLevel": "2.20", + "apiLevel": "2.21", } @@ -27,7 +27,7 @@ def run(protocol: protocol_api.ProtocolContext) -> None: reservoir_1 = protocol.load_labware( "nest_96_wellplate_2ml_deep", "D2", "Reservoir 1" ) # Reservoir - reservoir_2 = protocol.load_labware( + sample_plate_2 = protocol.load_labware( "thermoscientificnunc_96_wellplate_1300ul", "D3", "Sample Plate 2" ) # Reservoir sample_plate_1 = protocol.load_labware( @@ -57,10 +57,10 @@ def run(protocol: protocol_api.ProtocolContext) -> None: volume=[120, 750, 900, 96], source=source_reservoir["A1"], dest=[ - reservoir_1["A1"].top(), - reservoir_1["A2"].top(), - reservoir_1["A4"].top(), - reservoir_1["A5"].top(), + reservoir_1["A1"].top(), # AMPure + reservoir_1["A2"].top(), # SMB + reservoir_1["A4"].top(), # EtOH + reservoir_1["A5"].top(), # RSB ], blow_out=True, blowout_location="source well", @@ -68,10 +68,10 @@ def run(protocol: protocol_api.ProtocolContext) -> None: ) # Reservoir 2 Plate Prep: dispense liquid into columns 1-9 total 3690 ul - reservoir_2_wells = reservoir_2.wells() + reservoir_2_wells = sample_plate_1.wells() list_of_locations = [well_location.top() for well_location in reservoir_2_wells] p1000.transfer( - volume=[50, 50, 50, 50, 50, 50, 330, 330, 330, 800, 800, 800], + volume=[150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150], source=source_reservoir["A1"], dest=list_of_locations, blow_out=True, @@ -80,9 +80,14 @@ def run(protocol: protocol_api.ProtocolContext) -> None: ) # Sample Plate Prep: total 303 - dest_list = [sample_plate_1["A1"], sample_plate_1["A2"], sample_plate_1["A3"]] + dest_list = [ + sample_plate_2["A9"], + sample_plate_2["A10"], + sample_plate_2["A11"], + sample_plate_2["A12"], + ] p1000.transfer( - volume=[101, 101, 101], + volume=[1000, 1000, 1000, 1000], source=source_reservoir["A1"], dest=dest_list, blow_out=True, diff --git a/abr-testing/abr_testing/protocols/liquid_setups/5_96ch Complex Protocol Liquid Setup.py b/abr-testing/abr_testing/protocols/liquid_setups/5_96ch Complex Protocol Liquid Setup.py index cd263318442..e7a726b6b46 100644 --- a/abr-testing/abr_testing/protocols/liquid_setups/5_96ch Complex Protocol Liquid Setup.py +++ b/abr-testing/abr_testing/protocols/liquid_setups/5_96ch Complex Protocol Liquid Setup.py @@ -5,14 +5,14 @@ ) metadata = { - "protocolName": "DVT2ABR5 and 6 Liquids: 96ch Complex Protocol", + "protocolName": "DVT2ABR5 Liquids: 96ch Complex Protocol", "author": "Rhyann clarke ", "source": "Protocol Library", } requirements = { "robotType": "Flex", - "apiLevel": "2.16", + "apiLevel": "2.21", } @@ -29,7 +29,7 @@ def run(protocol: protocol_api.ProtocolContext) -> None: "nest_96_wellplate_2ml_deep", "D2", "Reservoir" ) # Reservoir - vol = 500 + vol = 1000 column_list = [ "A1", @@ -45,9 +45,9 @@ def run(protocol: protocol_api.ProtocolContext) -> None: "A11", "A12", ] + p1000.pick_up_tip() for i in column_list: - p1000.pick_up_tip() p1000.aspirate(vol, source_reservoir["A1"].bottom(z=0.5)) p1000.dispense(vol, reservoir[i].top()) p1000.blow_out(location=source_reservoir["A1"].top()) - p1000.return_tip() + p1000.return_tip() diff --git a/abr-testing/abr_testing/protocols/liquid_setups/7_HDQ DNA Bacteria Extraction Liquid Setup.py b/abr-testing/abr_testing/protocols/liquid_setups/7_HDQ DNA Bacteria Extraction Liquid Setup.py index 4addbd5c7e8..309f9916d03 100644 --- a/abr-testing/abr_testing/protocols/liquid_setups/7_HDQ DNA Bacteria Extraction Liquid Setup.py +++ b/abr-testing/abr_testing/protocols/liquid_setups/7_HDQ DNA Bacteria Extraction Liquid Setup.py @@ -13,7 +13,7 @@ requirements = { "robotType": "Flex", - "apiLevel": "2.16", + "apiLevel": "2.21", } @@ -55,9 +55,22 @@ def run(protocol: protocol_api.ProtocolContext) -> None: # Sample Plate p1000.transfer( - volume=180, + volume=200, source=source_reservoir["A1"].bottom(z=0.5), - dest=sample_plate["A1"].top(), + dest=[ + sample_plate["A1"].top(), + sample_plate["A2"].top(), + sample_plate["A3"].top(), + sample_plate["A4"].top(), + sample_plate["A5"].top(), + sample_plate["A6"].top(), + sample_plate["A7"].top(), + sample_plate["A8"].top(), + sample_plate["A9"].top(), + sample_plate["A10"].top(), + sample_plate["A11"].top(), + sample_plate["A12"].top(), + ], blowout=True, blowout_location="source well", trash=False, @@ -66,7 +79,20 @@ def run(protocol: protocol_api.ProtocolContext) -> None: p1000.transfer( volume=100, source=source_reservoir["A1"].bottom(z=0.5), - dest=elution_plate["A1"].top(), + dest=[ + elution_plate["A1"].top(), + elution_plate["A2"].top(), + elution_plate["A3"].top(), + elution_plate["A4"].top(), + elution_plate["A5"].top(), + elution_plate["A6"].top(), + elution_plate["A7"].top(), + elution_plate["A8"].top(), + elution_plate["A9"].top(), + elution_plate["A10"].top(), + elution_plate["A11"].top(), + elution_plate["A12"].top(), + ], blowout=True, blowout_location="source well", trash=False, diff --git a/abr-testing/abr_testing/protocols/liquid_setups/9_Thermo MagMax RNA Extraction Liquid Setup.py b/abr-testing/abr_testing/protocols/liquid_setups/9_Thermo MagMax RNA Extraction Liquid Setup.py index c6ded28719d..e935063ed16 100644 --- a/abr-testing/abr_testing/protocols/liquid_setups/9_Thermo MagMax RNA Extraction Liquid Setup.py +++ b/abr-testing/abr_testing/protocols/liquid_setups/9_Thermo MagMax RNA Extraction Liquid Setup.py @@ -13,7 +13,7 @@ requirements = { "robotType": "Flex", - "apiLevel": "2.16", + "apiLevel": "2.21", } @@ -34,15 +34,28 @@ def run(protocol: protocol_api.ProtocolContext) -> None: ) # Volumes + lysis = 8120 / 8 + stop_reaction_vol = 6400 / 8 elution_vol = 55 - well1 = 8120 / 8 - well2 = 6400 / 8 - well3_7 = 8550 / 8 + well4_12 = 9500 / 8 sample_vol = 100 # Reservoir p1000.transfer( - volume=[well1, well2, well3_7, well3_7, well3_7, well3_7, well3_7], + volume=[ + lysis, + lysis, + stop_reaction_vol, + well4_12, + well4_12, + well4_12, + well4_12, + well4_12, + well4_12, + well4_12, + well4_12, + well4_12, + ], source=source_reservoir["A1"].bottom(z=0.2), dest=[ res1["A1"].top(), @@ -52,6 +65,11 @@ def run(protocol: protocol_api.ProtocolContext) -> None: res1["A5"].top(), res1["A6"].top(), res1["A7"].top(), + res1["A8"].top(), + res1["A9"].top(), + res1["A10"].top(), + res1["A11"].top(), + res1["A12"].top(), ], blow_out=True, blowout_location="source well", @@ -94,7 +112,20 @@ def run(protocol: protocol_api.ProtocolContext) -> None: ) # Sample Plate p1000.transfer( - volume=[sample_vol, sample_vol, sample_vol, sample_vol, sample_vol, sample_vol], + volume=[ + sample_vol, + sample_vol, + sample_vol, + sample_vol, + sample_vol, + sample_vol, + sample_vol, + sample_vol, + sample_vol, + sample_vol, + sample_vol, + sample_vol, + ], source=source_reservoir["A1"].bottom(z=0.2), dest=[ sample_plate["A1"].top(), @@ -103,6 +134,12 @@ def run(protocol: protocol_api.ProtocolContext) -> None: sample_plate["A4"].top(), sample_plate["A5"].top(), sample_plate["A6"].top(), + sample_plate["A7"].top(), + sample_plate["A8"].top(), + sample_plate["A9"].top(), + sample_plate["A10"].top(), + sample_plate["A11"].top(), + sample_plate["A12"].top(), ], blow_out=True, blowout_location="source well", diff --git a/abr-testing/abr_testing/protocols/test_protocols/tc_lid_x_offset_test.py b/abr-testing/abr_testing/protocols/test_protocols/tc_lid_x_offset_test.py index df85453ff28..254a1b05514 100644 --- a/abr-testing/abr_testing/protocols/test_protocols/tc_lid_x_offset_test.py +++ b/abr-testing/abr_testing/protocols/test_protocols/tc_lid_x_offset_test.py @@ -23,8 +23,8 @@ def add_parameters(parameters: ParameterContext) -> None: default=5, ) parameters.add_float( - variable_name="x_offset", - display_name="X Offset", + variable_name="offset", + display_name="Z Offset", choices=[ {"display_name": "0.0", "value": 0.0}, {"display_name": "0.1", "value": 0.1}, @@ -62,10 +62,10 @@ def run(protocol: ProtocolContext) -> None: """Runs protocol that moves lids and stacks them.""" # Load Parameters lids_in_stack = protocol.params.lids_in_a_stack # type: ignore[attr-defined] - x_offset = protocol.params.x_offset # type: ignore[attr-defined] + offset = protocol.params.offset # type: ignore[attr-defined] negative = protocol.params.negative # type: ignore[attr-defined] if negative: - x_offset = x_offset * -1 + offset = offset * -1 # Thermocycler thermocycler: ThermocyclerContext = protocol.load_module( "thermocyclerModuleV2" @@ -81,16 +81,16 @@ def run(protocol: ProtocolContext) -> None: lid_stack_4 = helpers.load_disposable_lids(protocol, lids_in_stack, ["C3"]) lid_stack_5 = helpers.load_disposable_lids(protocol, lids_in_stack, ["B3"]) - drop_offset = {"x": x_offset, "y": 0, "z": 0} + pickup_offset = {"x": 0, "y": 0, "z": offset} slot = 0 lids = [lid_stack_1, lid_stack_2, lid_stack_3, lid_stack_4, lid_stack_5] for lid_list in lids: lid_to_move = lid_list[0] lid_to_move_back_to = lid_list[1] - protocol.comment(f"Offset {x_offset}, Lid # {slot+1}") + protocol.comment(f"Offset {offset}, Lid # {slot+1}") # move lid to plate in thermocycler protocol.move_labware( - lid_to_move, plate_in_cycler, use_gripper=True, drop_offset=drop_offset + lid_to_move, plate_in_cycler, use_gripper=True, pick_up_offset=pickup_offset ) protocol.move_labware(lid_to_move, lid_to_move_back_to, use_gripper=True) diff --git a/abr-testing/abr_testing/tools/abr_scale.py b/abr-testing/abr_testing/tools/abr_scale.py index a35fee93fbf..e91abf114b2 100644 --- a/abr-testing/abr_testing/tools/abr_scale.py +++ b/abr-testing/abr_testing/tools/abr_scale.py @@ -149,14 +149,11 @@ def get_most_recent_run_and_record( headers, runs_and_lpc, headers_lpc, - list_of_heights, ) = abr_google_drive.create_data_dictionary( most_recent_run_id, storage_directory, "", - labware, - accuracy, - hellma_plate_standards=hellma_file_values, + hellma_file_values, ) google_sheet_abr_data = google_sheets_tool.google_sheet( credentials_path, "ABR-run-data", tab_number=0 @@ -164,15 +161,6 @@ def get_most_recent_run_and_record( start_row = google_sheet_abr_data.get_index_row() + 1 google_sheet_abr_data.batch_update_cells(runs_and_robots, "A", start_row, "0") print("Wrote run to ABR-run-data") - # Add liquid height detection to abr sheet - google_sheet_ldf = google_sheets_tool.google_sheet( - credentials_path, "ABR-run-data", 4 - ) - start_row_lhd = google_sheet_ldf.get_index_row() + 1 - google_sheet_ldf.batch_update_cells( - list_of_heights, "A", start_row_lhd, "1795535088" - ) - print("Wrote found liquid heights to ABR-run-data") # Add LPC to google sheet google_sheet_lpc = google_sheets_tool.google_sheet( credentials_path, "ABR-LPC", tab_number=0 diff --git a/abr-testing/abr_testing/tools/abr_setup.py b/abr-testing/abr_testing/tools/abr_setup.py index 224ba5bf120..a084c54c4f9 100644 --- a/abr-testing/abr_testing/tools/abr_setup.py +++ b/abr-testing/abr_testing/tools/abr_setup.py @@ -42,7 +42,9 @@ def clean_sheet(sheet_name: str, credentials: str) -> Any: # Check if the date is older than the cutoff if formatted_date < cutoff_date: rem_rows.append(row_id) - if len(rem_rows) > 2000: + + # Limit rem_rows to 1500 at a time + if len(rem_rows) >= 1500: break if len(rem_rows) == 0: # No more rows to remove @@ -53,9 +55,7 @@ def clean_sheet(sheet_name: str, credentials: str) -> Any: sheet.batch_delete_rows(rem_rows) print("deleted rows") except Exception: - print("could not delete rows") - traceback.print_exc() - sys.exit(1) + return clean_sheet(sheet_name, credentials)