diff --git a/analyses-snapshot-testing/automation/data/protocols.py b/analyses-snapshot-testing/automation/data/protocols.py index 8e19251d49e..26891974304 100644 --- a/analyses-snapshot-testing/automation/data/protocols.py +++ b/analyses-snapshot-testing/automation/data/protocols.py @@ -751,6 +751,13 @@ class Protocols: robot="Flex", ) + # analyses-snapshot-testing/files/protocols/Flex_S_v2_21_P1000_96_GRIP_HS_MB_TC_TM_Smoke.py + Flex_S_v2_21_P1000_96_GRIP_HS_MB_TC_TM_Smoke: Protocol = Protocol( + file_stem="Flex_S_v2_21_P1000_96_GRIP_HS_MB_TC_TM_Smoke", + file_extension="py", + robot="Flex", + ) + OT2_X_v2_18_None_None_duplicateRTPVariableName: Protocol = Protocol( file_stem="OT2_X_v2_18_None_None_duplicateRTPVariableName", file_extension="py", diff --git a/analyses-snapshot-testing/files/protocols/Flex_S_v2_21_P1000_96_GRIP_HS_MB_TC_TM_Smoke.py b/analyses-snapshot-testing/files/protocols/Flex_S_v2_21_P1000_96_GRIP_HS_MB_TC_TM_Smoke.py new file mode 100644 index 00000000000..20d77fd560f --- /dev/null +++ b/analyses-snapshot-testing/files/protocols/Flex_S_v2_21_P1000_96_GRIP_HS_MB_TC_TM_Smoke.py @@ -0,0 +1,458 @@ +############# +# CHANGELOG # +############# + +# ---- +# 2.21 +# ---- + +# - - Run protocols that use the Absorbance Plate Reader and check the status of the module on the robot details screen for your Flex. +# - - Run protocols that use the new Opentrons Tough PCR Auto-Sealing Lid with the Thermocycler Module GEN2. Stacks of these lids appear in a consolidated view when setting up labware. +# - - Error recovery now works in more situations and has more options - Gripper Errors, Drop Tip Errors, additional recovery options for tip errors, disable error recovery entirely (8.2.0) + +# ---- +# 2.20 +# ---- + +# - configure_nozzle_layout() now accepts row, single, and partial column layout constants. See Partial Tip Pickup. +# - You can now call ProtocolContext.define_liquid() without supplying a description or display_color. +# - You can now call ProtocolContext.liquid_presence_detection() or ProtocolContext.require_liquid_presence() to use LLD on instrument context or on well +# - You now have the option to set RTP using CSV files +# - Error Recovery will now initiate for miss tip pick up, overpressure on aspirate and dispense, and if liquid presence isn't detected (8.0.0) + +# ---- +# 2.19 +# ---- + +# - NO FEATURES OR API CHANGES +# - New values for how much a tip overlaps with the pipette nozzle when the pipette picks up tips + +# ---- +# 2.18 +# ---- + +# - labware.set_offset +# - Runtime Parameters added +# - TrashContainer.top() and Well.top() now return objects of the same type +# - pipette.drop_tip() if location argument not specified the tips will be dropped at different locations in the bin +# - pipette.drop_tip() if location is specified, the tips will be dropped in the same place every time + +# ---- +# 2.17 +# ---- + +# NOTHING NEW +# This protocol is exactly the same as 2.16 Smoke Test V3 +# The only difference is the API version in the metadata +# There were no new positive test cases for 2.17 +# The negative test cases are captured in the 2.17 dispense changes protocol + +# ---- +# 2.16 +# ---- + +# - prepare_to_aspirate added +# - fixed_trash property changed +# - instrument_context.trash_container property changed + +# ---- +# 2.15 +# ---- + +# - move_labware added - Manual Deck State Modification +# - ProtocolContext.load_adapter added +# - OFF_DECK location added + +from typing import List +from opentrons import protocol_api, types +from opentrons.protocol_api import Labware + + +metadata = { + "protocolName": "Flex Smoke Test - v2.21", + "author": "QA team", +} + +requirements = { + "robotType": "Flex", + "apiLevel": "2.21", +} + + +################# +### CONSTANTS ### +################# + +DeckSlots = [ + "A1", + "A2", + "A3", + "A4", + "B1", + "B2", + "B3", + "B4", + "C1", + "C2", + "C3", + "C4", + "D1", + "D2", + "D3", + "D4", +] + +HEATER_SHAKER_ADAPTER_NAME = "opentrons_96_pcr_adapter" +HEATER_SHAKER_NAME = "heaterShakerModuleV1" +MAGNETIC_BLOCK_NAME = "magneticBlockV1" +TEMPERATURE_MODULE_ADAPTER_NAME = "opentrons_96_well_aluminum_block" +TEMPERATURE_MODULE_NAME = "temperature module gen2" +THERMOCYCLER_NAME = "thermocycler module gen2" +ABSORBANCE_READER = "absorbanceReaderV1" +DECK_RISER_NAME = "opentrons_flex_deck_riser" +TC_LID = "opentrons_tough_pcr_auto_sealing_lid" +LID_COUNT = 5 +TIPRACK_96_ADAPTER_NAME = "opentrons_flex_96_tiprack_adapter" +TIPRACK_96_NAME = "opentrons_flex_96_tiprack_1000ul" +PIPETTE_96_CHANNEL_NAME = "flex_96channel_1000" +WELL_PLATE_STARTING_POSITION = "C2" +RESERVOIR_STARTING_POSITION = "D2" + + +def comment_tip_rack_status(ctx, tip_rack): + """ + Print out the tip status for each row in a tip rack. + Each row (A-H) will print the well statuses for columns 1-12 in a single comment, + with a '🟢' for present tips and a '❌' for missing tips. + """ + range_A_to_H = [chr(i) for i in range(ord("A"), ord("H") + 1)] + range_1_to_12 = range(1, 13) + + ctx.comment(f"Tip rack in {tip_rack.parent}") + + for row in range_A_to_H: + status_line = f"{row}: " + for col in range_1_to_12: + well = f"{row}{col}" + has_tip = tip_rack.wells_by_name()[well].has_tip + status_emoji = "🟢" if has_tip else "❌" + status_line += f"{well} {status_emoji} " + + # Print the full status line for the row + ctx.comment(status_line) + + +############################## +# Runtime Parameters Support # +############################## + +# -------------------------- # +# Added in API version: 2.18 # +# -------------------------- # + + +def add_parameters(parameters: protocol_api.Parameters): + """This is the standard use of parameters""" + + # We are using the defaults for every case. + # Other tests cover regression testing for + # other types of parameters and UI appearance + # there are many tests in Analyses Battery that cover errors and edge cases + + parameters.add_str( + variable_name="test_configuration", + display_name="Test Configuration", + description="Configuration of QA test to perform", + default="full", + choices=[{"display_name": "Full Smoke Test", "value": "full"}], + ) + + parameters.add_str( + variable_name="reservoir_name", + display_name="Reservoir Name", + description="Name of the reservoir", + default="nest_1_reservoir_290ml", + choices=[{"display_name": "Nest 1 Well 290 mL", "value": "nest_1_reservoir_290ml"}], + ) + + parameters.add_str( + variable_name="well_plate_name", + display_name="Well Plate Name", + description="Name of the well plate", + default="opentrons_96_wellplate_200ul_pcr_full_skirt", + choices=[{"display_name": "Opentrons Tough 96 Well 200 µL", "value": "opentrons_96_wellplate_200ul_pcr_full_skirt"}], + ) + + +def log_position(ctx, item): + ctx.comment(f"Item {item.load_name} is at {item.parent}") + + +def run(ctx: protocol_api.ProtocolContext) -> None: + + ################ + ### FIXTURES ### + ################ + + waste_chute = ctx.load_waste_chute() + + ############### + ### MODULES ### + ############### + deck_riser_adapter = ctx.load_adapter(DECK_RISER_NAME, "A4") + thermocycler = ctx.load_module(THERMOCYCLER_NAME) # A1 & B1 + magnetic_block = ctx.load_module(MAGNETIC_BLOCK_NAME, "A3") + heater_shaker = ctx.load_module(HEATER_SHAKER_NAME, "C1") + temperature_module = ctx.load_module(TEMPERATURE_MODULE_NAME, "D1") + absorbance_module = ctx.load_module(ABSORBANCE_READER, "B3") + + lids: List[Labware] = [deck_riser_adapter.load_labware(TC_LID)] + for i in range(LID_COUNT - 1): + lids.append(lids[-1].load_labware(TC_LID)) + lids.reverse() + + thermocycler.open_lid() + heater_shaker.open_labware_latch() + absorbance_module.close_lid() + absorbance_module.initialize("single", [600], 450) + absorbance_module.open_lid() + + ####################### + ### MODULE ADAPTERS ### + ####################### + + temperature_module_adapter = temperature_module.load_adapter(TEMPERATURE_MODULE_ADAPTER_NAME) + heater_shaker_adapter = heater_shaker.load_adapter(HEATER_SHAKER_ADAPTER_NAME) + adapters = [temperature_module_adapter, heater_shaker_adapter] + + ############### + ### LABWARE ### + ############### + + # Load these directly with the RTP + source_reservoir = ctx.load_labware(ctx.params.reservoir_name, RESERVOIR_STARTING_POSITION) + dest_pcr_plate = ctx.load_labware(ctx.params.well_plate_name, WELL_PLATE_STARTING_POSITION) + + tip_rack_1 = ctx.load_labware(TIPRACK_96_NAME, "A2", adapter=TIPRACK_96_ADAPTER_NAME) + 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_5 = ctx.load_labware(TIPRACK_96_NAME, protocol_api.OFF_DECK) + + tip_racks = [tip_rack_1, tip_rack_2, tip_rack_3] + + ########################## + ### PIPETTE DEFINITION ### + ########################## + + pipette_96_channel = ctx.load_instrument(PIPETTE_96_CHANNEL_NAME, mount="left", tip_racks=tip_racks, liquid_presence_detection=True) + pipette_96_channel.trash_container = waste_chute + + assert isinstance(pipette_96_channel.trash_container, protocol_api.WasteChute) + + ######################## + ### LOAD SOME LIQUID ### + ######################## + + water = ctx.define_liquid(name="water", description="High Quality H₂O", display_color="#42AB2D") + source_reservoir.wells_by_name()["A1"].load_liquid(liquid=water, volume=29000) + + ################################ + ### GRIPPER LABWARE MOVEMENT ### + ################################ + + log_position(ctx, dest_pcr_plate) + ctx.move_labware(dest_pcr_plate, thermocycler, use_gripper=True) + log_position(ctx, dest_pcr_plate) + # Move it back to the deck + ctx.move_labware(dest_pcr_plate, "C2", use_gripper=True) + log_position(ctx, dest_pcr_plate) + + # Other important moves? + + # manual move + log_position(ctx, source_reservoir) + ctx.move_labware(source_reservoir, "D4", use_gripper=False) + log_position(ctx, source_reservoir) + ctx.move_labware(source_reservoir, RESERVOIR_STARTING_POSITION, use_gripper=True) + log_position(ctx, source_reservoir) + + # Other important manual moves? + + # 96 channel column pickup + pipette_96_channel.configure_nozzle_layout(style=protocol_api.COLUMN, start="A12") + pipette_96_channel.pick_up_tip(tip_rack_2["A1"]) + comment_tip_rack_status(ctx, tip_rack_2) + pipette_96_channel.aspirate(5, source_reservoir["A1"]) + pipette_96_channel.touch_tip() + pipette_96_channel.dispense(5, dest_pcr_plate[f"A1"]) + pipette_96_channel.drop_tip(waste_chute) + + # 96 channel single pickup + pipette_96_channel.configure_nozzle_layout(style=protocol_api.SINGLE, start="H12") + pipette_96_channel.pick_up_tip(tip_rack_2) + pipette_96_channel.aspirate(5, source_reservoir["A1"]) + pipette_96_channel.touch_tip() + pipette_96_channel.dispense(5, source_reservoir["A1"]) + pipette_96_channel.aspirate(500, source_reservoir["A1"]) + pipette_96_channel.dispense(500, source_reservoir["A1"]) + pipette_96_channel.drop_tip(waste_chute) + comment_tip_rack_status(ctx, tip_rack_2) + + # put the tip rack in the trash + # since it cannot have a row pickup + ctx.move_labware(tip_rack_2, waste_chute, use_gripper=True) + ctx.move_labware(tip_rack_3, "C3", use_gripper=True) + + # 96 channel row pickup + pipette_96_channel.configure_nozzle_layout(style=protocol_api.ROW, start="H1") + pipette_96_channel.pick_up_tip(tip_rack_3) + pipette_96_channel.mix(3, 500, source_reservoir["A1"]) + pipette_96_channel.drop_tip(waste_chute) + comment_tip_rack_status(ctx, tip_rack_3) + + # 96 channel full rack pickup + pipette_96_channel.configure_nozzle_layout(style=protocol_api.ALL, start="A1") + pipette_96_channel.pick_up_tip(tip_rack_1["A1"]) + comment_tip_rack_status(ctx, tip_rack_1) + 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(waste_chute) + pipette_96_channel.prepare_to_aspirate() + 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(waste_chute) + pipette_96_channel.prepare_to_aspirate() + pipette_96_channel.aspirate(10, source_reservoir["A1"]) + pipette_96_channel.touch_tip() + pipette_96_channel.dispense(10, dest_pcr_plate["A1"]) + pipette_96_channel.mix(repetitions=5, volume=15) + pipette_96_channel.return_tip() + comment_tip_rack_status(ctx, tip_rack_1) + pipette_96_channel.pick_up_tip(tip_rack_1["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), + ) + comment_tip_rack_status(ctx, tip_rack_1) + pipette_96_channel.return_tip(home_after=False) + comment_tip_rack_status(ctx, tip_rack_1) + ctx.comment("I think the above should not be empty?") + # Thermocycler lid moves + ctx.move_labware(dest_pcr_plate, thermocycler, use_gripper=True) + ctx.move_labware(lids[0], dest_pcr_plate, use_gripper=True) # we reversed this list earlier + thermocycler.close_lid() + thermocycler.set_block_temperature(38, hold_time_seconds=5.0) + thermocycler.set_lid_temperature(38) + thermocycler.open_lid() + ctx.move_labware(lids[0], waste_chute, use_gripper=True) + thermocycler.deactivate() + + heater_shaker.open_labware_latch() + ctx.move_labware(dest_pcr_plate, heater_shaker_adapter, use_gripper=True) + heater_shaker.close_labware_latch() + + heater_shaker.set_target_temperature(38) + heater_shaker.set_and_wait_for_shake_speed(777) + heater_shaker.wait_for_temperature() + + heater_shaker.deactivate_heater() + heater_shaker.deactivate_shaker() + heater_shaker.open_labware_latch() + + ctx.move_labware(dest_pcr_plate, temperature_module_adapter, use_gripper=True) + temperature_module.set_temperature(38) + temperature_module.deactivate() + + ctx.move_labware(dest_pcr_plate, absorbance_module, use_gripper=True) + absorbance_module.close_lid() + + result = absorbance_module.read(export_filename="smoke_APR_data.csv") + msg = f"single: {result}" + ctx.comment(msg=msg) + ctx.pause(msg=msg) + absorbance_module.open_lid() + ctx.move_labware(dest_pcr_plate, "C2", use_gripper=True) + + # ###################### + # # labware.set_offset # + # ###################### + + # # -------------------------- # + # # Added in API version: 2.18 # + # # -------------------------- # + + SET_OFFSET_AMOUNT = 10.0 + ctx.move_labware(labware=source_reservoir, new_location=protocol_api.OFF_DECK, use_gripper=False) + pipette_96_channel.pick_up_tip(tip_rack_1["A1"]) + pipette_96_channel.move_to(dest_pcr_plate.wells_by_name()["A1"].top()) + + ctx.pause("Is the pipette tip in the middle of the PCR Plate, well A1, in slot C2? It should be at the LPC calibrated height.") + + dest_pcr_plate.set_offset( + x=0.0, + y=0.0, + z=SET_OFFSET_AMOUNT, + ) + + pipette_96_channel.move_to(dest_pcr_plate.wells_by_name()["A1"].top()) + ctx.pause( + "Is the pipette tip in the middle of the PCR Plate, well A1, in slot C2? It should be 10mm higher than the LPC calibrated height." + ) + + ctx.move_labware(labware=dest_pcr_plate, new_location="D2", use_gripper=False) + pipette_96_channel.move_to(dest_pcr_plate.wells_by_name()["A1"].top()) + + ctx.pause("Is the pipette tip in the middle of the PCR Plate, well A1, in slot D2? It should be at the LPC calibrated height.") + + dest_pcr_plate.set_offset( + x=0.0, + y=0.0, + z=SET_OFFSET_AMOUNT, + ) + + pipette_96_channel.move_to(dest_pcr_plate.wells_by_name()["A1"].top()) + ctx.pause( + "Is the pipette tip in the middle of the PCR Plate, well A1, in slot D2? It should be 10mm higher than the LPC calibrated height." + ) + + ctx.move_labware(labware=dest_pcr_plate, new_location="C2", use_gripper=False) + pipette_96_channel.move_to(dest_pcr_plate.wells_by_name()["A1"].top()) + + ctx.pause( + "Is the pipette tip in the middle of the PCR Plate, well A1, in slot C2? It should be 10mm higher than the LPC calibrated height." + ) + + ctx.move_labware(labware=source_reservoir, new_location="D2", use_gripper=False) + pipette_96_channel.move_to(source_reservoir.wells_by_name()["A1"].top()) + + ctx.pause("Is the pipette tip in the middle of the reservoir , well A1, in slot D2? It should be at the LPC calibrated height.") + + pipette_96_channel.return_tip() + ctx.move_labware(tip_rack_3, waste_chute, use_gripper=True) + + ctx.pause("!!!!!!!!!!YOU NEED TO REDO LPC!!!!!!!!!!") + + # Test the unique top() methods for TrashBin and WasteChute. + # Well objects should remain the same + + ######################## + # unique top() methods # + ######################## + + # ---------------------------- # + # Changed in API version: 2.18 # + # ---------------------------- # + + assert isinstance(waste_chute.top(), protocol_api.WasteChute) + assert isinstance(source_reservoir.wells_by_name()["A1"].top(), types.Location) diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[00574c503f][pl_BacteriaInoculation_Flex_6plates].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[00574c503f][pl_BacteriaInoculation_Flex_6plates].json index 0a408e946c3..0cf14e731b6 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[00574c503f][pl_BacteriaInoculation_Flex_6plates].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[00574c503f][pl_BacteriaInoculation_Flex_6plates].json @@ -982,6 +982,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[0903a95825][Flex_S_v2_19_QIASeq_FX_48x].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[0903a95825][Flex_S_v2_19_QIASeq_FX_48x].json index a7e09aba292..fccf2aae96c 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[0903a95825][Flex_S_v2_19_QIASeq_FX_48x].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[0903a95825][Flex_S_v2_19_QIASeq_FX_48x].json @@ -5144,6 +5144,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[0a9ef592c8][Flex_S_v2_18_Illumina_DNA_Prep_48x].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[0a9ef592c8][Flex_S_v2_18_Illumina_DNA_Prep_48x].json index 705c9658155..b49eaeb6609 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[0a9ef592c8][Flex_S_v2_18_Illumina_DNA_Prep_48x].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[0a9ef592c8][Flex_S_v2_18_Illumina_DNA_Prep_48x].json @@ -5205,6 +5205,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[0dd21c0ee5][pl_EM_seq_48Samples_AllSteps_Edits_150].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[0dd21c0ee5][pl_EM_seq_48Samples_AllSteps_Edits_150].json index b964f2a7367..c407d673c2b 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[0dd21c0ee5][pl_EM_seq_48Samples_AllSteps_Edits_150].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[0dd21c0ee5][pl_EM_seq_48Samples_AllSteps_Edits_150].json @@ -8631,6 +8631,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -9909,6 +9914,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[13ec753045][Flex_S_v2_18_Illumina_Stranded_total_RNA_Ribo_Zero].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[13ec753045][Flex_S_v2_18_Illumina_Stranded_total_RNA_Ribo_Zero].json index 087cbb927b9..8701aae97bc 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[13ec753045][Flex_S_v2_18_Illumina_Stranded_total_RNA_Ribo_Zero].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[13ec753045][Flex_S_v2_18_Illumina_Stranded_total_RNA_Ribo_Zero].json @@ -3283,6 +3283,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[15a60fccf4][pl_microBioID_beads_touchtip].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[15a60fccf4][pl_microBioID_beads_touchtip].json index 6b7d81ff805..0363b1ca1df 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[15a60fccf4][pl_microBioID_beads_touchtip].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[15a60fccf4][pl_microBioID_beads_touchtip].json @@ -3576,6 +3576,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[1b73b8a126][pl_Dynabeads_IP_Flex_96well_RIT_final].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[1b73b8a126][pl_Dynabeads_IP_Flex_96well_RIT_final].json index 29df1897867..a084faeeb15 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[1b73b8a126][pl_Dynabeads_IP_Flex_96well_RIT_final].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[1b73b8a126][pl_Dynabeads_IP_Flex_96well_RIT_final].json @@ -305,6 +305,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -6222,6 +6227,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[1d37cbc080][pl_MagMax_RNA_Cells_Flex_multi].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[1d37cbc080][pl_MagMax_RNA_Cells_Flex_multi].json index 03bb82c7b3c..7d89bcbae0c 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[1d37cbc080][pl_MagMax_RNA_Cells_Flex_multi].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[1d37cbc080][pl_MagMax_RNA_Cells_Flex_multi].json @@ -829,6 +829,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[248a2a3107][pl_Omega_HDQ_DNA_Cells_Flex_96_channel].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[248a2a3107][pl_Omega_HDQ_DNA_Cells_Flex_96_channel].json index 427cd1c997b..38d0810f4ad 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[248a2a3107][pl_Omega_HDQ_DNA_Cells_Flex_96_channel].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[248a2a3107][pl_Omega_HDQ_DNA_Cells_Flex_96_channel].json @@ -829,6 +829,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -5067,6 +5072,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -9802,6 +9812,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -14537,6 +14552,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -17544,6 +17564,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[277961bc58][pl_NiNTA_Flex_96well_final].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[277961bc58][pl_NiNTA_Flex_96well_final].json index 7602c8613f4..64cec1732c3 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[277961bc58][pl_NiNTA_Flex_96well_final].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[277961bc58][pl_NiNTA_Flex_96well_final].json @@ -305,6 +305,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -1584,6 +1589,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -2863,6 +2873,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -4142,6 +4157,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -8375,6 +8395,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[28fdeebdd9][pl_Omega_HDQ_DNA_Cells_Flex_multi].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[28fdeebdd9][pl_Omega_HDQ_DNA_Cells_Flex_multi].json index 1598272fc5c..936161f35e0 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[28fdeebdd9][pl_Omega_HDQ_DNA_Cells_Flex_multi].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[28fdeebdd9][pl_Omega_HDQ_DNA_Cells_Flex_multi].json @@ -829,6 +829,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[29bb5df52d][pl_Omega_HDQ_DNA_Bacteria_Flex_multi].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[29bb5df52d][pl_Omega_HDQ_DNA_Bacteria_Flex_multi].json index d6a2126b774..bce6b1bfc5c 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[29bb5df52d][pl_Omega_HDQ_DNA_Bacteria_Flex_multi].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[29bb5df52d][pl_Omega_HDQ_DNA_Bacteria_Flex_multi].json @@ -829,6 +829,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[2b866b03f3][Flex_S_v2_21_P1000_96_GRIP_HS_MB_TC_TM_Smoke].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[2b866b03f3][Flex_S_v2_21_P1000_96_GRIP_HS_MB_TC_TM_Smoke].json new file mode 100644 index 00000000000..ee19bc58e32 --- /dev/null +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[2b866b03f3][Flex_S_v2_21_P1000_96_GRIP_HS_MB_TC_TM_Smoke].json @@ -0,0 +1,15150 @@ +{ + "commandAnnotations": [], + "commands": [ + { + "commandType": "home", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "50c7ae73a4e3f7129874f39dfb514803", + "notes": [], + "params": {}, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "loadLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "73d9d4d55ae8466f3a793ceb70545fa5", + "notes": [], + "params": { + "loadName": "opentrons_flex_deck_riser", + "location": { + "addressableAreaName": "A4" + }, + "namespace": "opentrons", + "version": 1 + }, + "result": { + "definition": { + "allowedRoles": [ + "adapter" + ], + "brand": { + "brand": "Opentrons", + "brandId": [] + }, + "cornerOffsetFromSlot": { + "x": -6.125, + "y": -6.125, + "z": 0 + }, + "dimensions": { + "xDimension": 140, + "yDimension": 98, + "zDimension": 55 + }, + "gripperOffsets": {}, + "groups": [ + { + "metadata": {}, + "wells": [] + } + ], + "metadata": { + "displayCategory": "adapter", + "displayName": "Opentrons Flex Deck Riser", + "displayVolumeUnits": "µL", + "tags": [] + }, + "namespace": "opentrons", + "ordering": [], + "parameters": { + "format": "96Standard", + "isMagneticModuleCompatible": false, + "isTiprack": false, + "loadName": "opentrons_flex_deck_riser", + "quirks": [] + }, + "schemaVersion": 2, + "stackingOffsetWithLabware": {}, + "stackingOffsetWithModule": {}, + "version": 1, + "wells": {} + }, + "labwareId": "UUID" + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "loadModule", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "a3a7eed460d8d94a91747f23820a180d", + "notes": [], + "params": { + "location": { + "slotName": "B1" + }, + "model": "thermocyclerModuleV2" + }, + "result": { + "definition": { + "calibrationPoint": { + "x": 14.4, + "y": 64.93, + "z": 97.8 + }, + "compatibleWith": [], + "dimensions": { + "bareOverallHeight": 108.96, + "lidHeight": 61.7, + "overLabwareHeight": 0.0 + }, + "displayName": "Thermocycler Module GEN2", + "gripperOffsets": { + "default": { + "dropOffset": { + "x": 0.0, + "y": 0.0, + "z": 5.6 + }, + "pickUpOffset": { + "x": 0.0, + "y": 0.0, + "z": 4.6 + } + } + }, + "labwareOffset": { + "x": 0.0, + "y": 68.8, + "z": 108.96 + }, + "model": "thermocyclerModuleV2", + "moduleType": "thermocyclerModuleType", + "otSharedSchema": "module/schemas/2", + "quirks": [], + "slotTransforms": { + "ot3_standard": { + "B1": { + "cornerOffsetFromSlot": [ + [ + -98, + 0, + 0, + 1 + ], + [ + -20.005, + 0, + 0, + 1 + ], + [ + -0.84, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ] + ], + "labwareOffset": [ + [ + -98, + 0, + 0, + 1 + ], + [ + -20.005, + 0, + 0, + 1 + ], + [ + -0.84, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ] + ] + } + } + } + }, + "model": "thermocyclerModuleV2", + "moduleId": "UUID", + "serialNumber": "UUID" + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "loadModule", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "d023a31e37dd4dd97dbd40857a7508ed", + "notes": [], + "params": { + "location": { + "slotName": "A3" + }, + "model": "magneticBlockV1" + }, + "result": { + "definition": { + "calibrationPoint": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "compatibleWith": [], + "dimensions": { + "bareOverallHeight": 45.0, + "overLabwareHeight": 0.0 + }, + "displayName": "Magnetic Block GEN1", + "gripperOffsets": { + "default": { + "dropOffset": { + "x": 0.0, + "y": 0.0, + "z": 1.0 + }, + "pickUpOffset": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + } + } + }, + "labwareOffset": { + "x": 0.0, + "y": 0.0, + "z": 38.0 + }, + "model": "magneticBlockV1", + "moduleType": "magneticBlockType", + "otSharedSchema": "module/schemas/2", + "quirks": [], + "slotTransforms": { + "ot2_short_trash": {}, + "ot2_standard": {}, + "ot3_standard": {} + } + }, + "model": "magneticBlockV1", + "moduleId": "UUID" + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "loadModule", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "82d736bcccf3c45130f7959c3031b04c", + "notes": [], + "params": { + "location": { + "slotName": "C1" + }, + "model": "heaterShakerModuleV1" + }, + "result": { + "definition": { + "calibrationPoint": { + "x": 12.0, + "y": 8.75, + "z": 68.275 + }, + "compatibleWith": [], + "dimensions": { + "bareOverallHeight": 82.0, + "overLabwareHeight": 0.0 + }, + "displayName": "Heater-Shaker Module GEN1", + "gripperOffsets": { + "default": { + "dropOffset": { + "x": 0.0, + "y": 0.0, + "z": 1.0 + }, + "pickUpOffset": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + } + } + }, + "labwareOffset": { + "x": -0.125, + "y": 1.125, + "z": 68.275 + }, + "model": "heaterShakerModuleV1", + "moduleType": "heaterShakerModuleType", + "otSharedSchema": "module/schemas/2", + "quirks": [], + "slotTransforms": { + "ot2_short_trash": { + "3": { + "labwareOffset": [ + [ + -1, + 0, + 0, + 0 + ], + [ + -1, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ] + ] + }, + "6": { + "labwareOffset": [ + [ + -1, + 0, + 0, + 0 + ], + [ + -1, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ] + ] + }, + "9": { + "labwareOffset": [ + [ + -1, + 0, + 0, + 0 + ], + [ + -1, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ] + ] + } + }, + "ot2_standard": { + "3": { + "labwareOffset": [ + [ + -1, + 0, + 0, + 0 + ], + [ + -1, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ] + ] + }, + "6": { + "labwareOffset": [ + [ + -1, + 0, + 0, + 0 + ], + [ + -1, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ] + ] + }, + "9": { + "labwareOffset": [ + [ + -1, + 0, + 0, + 0 + ], + [ + -1, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ] + ] + } + }, + "ot3_standard": { + "A1": { + "labwareOffset": [ + [ + -49.325, + 0, + 0, + 1 + ], + [ + -1.125, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0.125, + 1 + ] + ] + }, + "A3": { + "labwareOffset": [ + [ + -49.325, + 0, + 0, + 1 + ], + [ + -1.125, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0.125, + 1 + ] + ] + }, + "B1": { + "labwareOffset": [ + [ + -49.325, + 0, + 0, + 1 + ], + [ + -1.125, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0.125, + 1 + ] + ] + }, + "B3": { + "labwareOffset": [ + [ + -49.325, + 0, + 0, + 1 + ], + [ + -1.125, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0.125, + 1 + ] + ] + }, + "C1": { + "labwareOffset": [ + [ + -49.325, + 0, + 0, + 1 + ], + [ + -1.125, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0.125, + 1 + ] + ] + }, + "C3": { + "labwareOffset": [ + [ + -49.325, + 0, + 0, + 1 + ], + [ + -1.125, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0.125, + 1 + ] + ] + }, + "D1": { + "labwareOffset": [ + [ + -49.325, + 0, + 0, + 1 + ], + [ + -1.125, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0.125, + 1 + ] + ] + }, + "D3": { + "labwareOffset": [ + [ + -49.325, + 0, + 0, + 1 + ], + [ + -1.125, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0.125, + 1 + ] + ] + } + } + } + }, + "model": "heaterShakerModuleV1", + "moduleId": "UUID", + "serialNumber": "UUID" + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "loadModule", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "1cef18851df21f75ea1c1d79e34dfdaf", + "notes": [], + "params": { + "location": { + "slotName": "D1" + }, + "model": "temperatureModuleV2" + }, + "result": { + "definition": { + "calibrationPoint": { + "x": 11.7, + "y": 8.75, + "z": 80.09 + }, + "compatibleWith": [ + "temperatureModuleV1" + ], + "dimensions": { + "bareOverallHeight": 84.0, + "overLabwareHeight": 0.0 + }, + "displayName": "Temperature Module GEN2", + "gripperOffsets": { + "default": { + "dropOffset": { + "x": 0.0, + "y": 0.0, + "z": 1.0 + }, + "pickUpOffset": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + } + } + }, + "labwareOffset": { + "x": -1.45, + "y": -0.15, + "z": 80.09 + }, + "model": "temperatureModuleV2", + "moduleType": "temperatureModuleType", + "otSharedSchema": "module/schemas/2", + "quirks": [], + "slotTransforms": { + "ot2_short_trash": { + "3": { + "labwareOffset": [ + [ + -1, + -0.15, + 0, + 0 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ] + ] + }, + "6": { + "labwareOffset": [ + [ + -1, + -0.15, + 0, + 0 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ] + ] + }, + "9": { + "labwareOffset": [ + [ + -1, + -0.15, + 0, + 0 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ] + ] + } + }, + "ot2_standard": { + "3": { + "labwareOffset": [ + [ + -1, + -0.3, + 0, + 0 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ] + ] + }, + "6": { + "labwareOffset": [ + [ + -1, + -0.3, + 0, + 0 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ] + ] + }, + "9": { + "labwareOffset": [ + [ + -1, + -0.3, + 0, + 0 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ] + ] + } + }, + "ot3_standard": { + "A1": { + "labwareOffset": [ + [ + -71.09, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0.15, + 1 + ], + [ + 0, + 0, + 1, + 1.45 + ] + ] + }, + "A3": { + "labwareOffset": [ + [ + -71.09, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0.15, + 1 + ], + [ + 0, + 0, + 1, + 1.45 + ] + ] + }, + "B1": { + "labwareOffset": [ + [ + -71.09, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0.15, + 1 + ], + [ + 0, + 0, + 1, + 1.45 + ] + ] + }, + "B3": { + "labwareOffset": [ + [ + -71.09, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0.15, + 1 + ], + [ + 0, + 0, + 1, + 1.45 + ] + ] + }, + "C1": { + "labwareOffset": [ + [ + -71.09, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0.15, + 1 + ], + [ + 0, + 0, + 1, + 1.45 + ] + ] + }, + "C3": { + "labwareOffset": [ + [ + -71.09, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0.15, + 1 + ], + [ + 0, + 0, + 1, + 1.45 + ] + ] + }, + "D1": { + "labwareOffset": [ + [ + -71.09, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0.15, + 1 + ], + [ + 0, + 0, + 1, + 1.45 + ] + ] + }, + "D3": { + "labwareOffset": [ + [ + -71.09, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 0.15, + 1 + ], + [ + 0, + 0, + 1, + 1.45 + ] + ] + } + } + } + }, + "model": "temperatureModuleV2", + "moduleId": "UUID", + "serialNumber": "UUID" + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "loadModule", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "0f830ddf4178d19d8afc9d9b7fbfb9e8", + "notes": [], + "params": { + "location": { + "slotName": "B3" + }, + "model": "absorbanceReaderV1" + }, + "result": { + "definition": { + "calibrationPoint": { + "x": 14.4, + "y": 64.93, + "z": 97.8 + }, + "compatibleWith": [], + "dimensions": { + "bareOverallHeight": 18.5, + "lidHeight": 60.0, + "overLabwareHeight": 0.0 + }, + "displayName": "Absorbance Plate Reader Module GEN1", + "gripperOffsets": {}, + "labwareOffset": { + "x": 0.0, + "y": 0.0, + "z": 0.65 + }, + "model": "absorbanceReaderV1", + "moduleType": "absorbanceReaderType", + "otSharedSchema": "module/schemas/2", + "quirks": [], + "slotTransforms": { + "ot2_short_trash": {}, + "ot2_standard": {}, + "ot3_standard": {} + } + }, + "model": "absorbanceReaderV1", + "moduleId": "UUID", + "serialNumber": "UUID" + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "loadLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "4c98abe700f8e8b07fba59c9e44932aa", + "notes": [], + "params": { + "loadName": "opentrons_tough_pcr_auto_sealing_lid", + "location": { + "labwareId": "UUID" + }, + "namespace": "opentrons", + "version": 1 + }, + "result": { + "definition": { + "allowedRoles": [ + "labware", + "lid" + ], + "brand": { + "brand": "Opentrons", + "brandId": [] + }, + "compatibleParentLabware": [ + "armadillo_96_wellplate_200ul_pcr_full_skirt", + "biorad_96_wellplate_200ul_pcr", + "opentrons_96_wellplate_200ul_pcr_full_skirt", + "opentrons_flex_deck_riser", + "opentrons_tough_pcr_auto_sealing_lid", + "protocol_engine_lid_stack_object" + ], + "cornerOffsetFromSlot": { + "x": 0, + "y": 0, + "z": -0.71 + }, + "dimensions": { + "xDimension": 127.7, + "yDimension": 85.48, + "zDimension": 12.8 + }, + "gripForce": 15.0, + "gripHeightFromLabwareBottom": 7.91, + "gripperOffsets": { + "default": { + "dropOffset": { + "x": 0, + "y": 0.52, + "z": -6 + }, + "pickUpOffset": { + "x": 0, + "y": 0, + "z": 1.5 + } + }, + "lidDisposalOffsets": { + "dropOffset": { + "x": 0, + "y": 5.0, + "z": 50.0 + }, + "pickUpOffset": { + "x": 0, + "y": 0, + "z": 0 + } + }, + "lidOffsets": { + "dropOffset": { + "x": 0.5, + "y": 0, + "z": -1 + }, + "pickUpOffset": { + "x": 0.5, + "y": 0, + "z": -5 + } + } + }, + "groups": [ + { + "metadata": {}, + "wells": [] + } + ], + "metadata": { + "displayCategory": "lid", + "displayName": "Opentrons Tough PCR Auto-Sealing Lid", + "displayVolumeUnits": "µL", + "tags": [] + }, + "namespace": "opentrons", + "ordering": [], + "parameters": { + "format": "irregular", + "isMagneticModuleCompatible": false, + "isTiprack": false, + "loadName": "opentrons_tough_pcr_auto_sealing_lid", + "quirks": [] + }, + "schemaVersion": 3, + "stackLimit": 5, + "stackingOffsetWithLabware": { + "armadillo_96_wellplate_200ul_pcr_full_skirt": { + "x": 0, + "y": 0, + "z": 8.193 + }, + "biorad_96_wellplate_200ul_pcr": { + "x": 0, + "y": 0, + "z": 8.08 + }, + "default": { + "x": 0, + "y": 0, + "z": 8.193 + }, + "opentrons_96_wellplate_200ul_pcr_full_skirt": { + "x": 0, + "y": 0, + "z": 8.193 + }, + "opentrons_flex_deck_riser": { + "x": 0, + "y": 0, + "z": 34 + }, + "opentrons_tough_pcr_auto_sealing_lid": { + "x": 0, + "y": 0, + "z": 6.492 + }, + "protocol_engine_lid_stack_object": { + "x": 0, + "y": 0, + "z": 0 + } + }, + "stackingOffsetWithModule": { + "thermocyclerModuleV2": { + "x": 0, + "y": 0, + "z": 0 + } + }, + "version": 1, + "wells": {} + }, + "labwareId": "UUID" + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "loadLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "61052a1834817792ac57ca3c95f8906a", + "notes": [], + "params": { + "loadName": "opentrons_tough_pcr_auto_sealing_lid", + "location": { + "labwareId": "UUID" + }, + "namespace": "opentrons", + "version": 1 + }, + "result": { + "definition": { + "allowedRoles": [ + "labware", + "lid" + ], + "brand": { + "brand": "Opentrons", + "brandId": [] + }, + "compatibleParentLabware": [ + "armadillo_96_wellplate_200ul_pcr_full_skirt", + "biorad_96_wellplate_200ul_pcr", + "opentrons_96_wellplate_200ul_pcr_full_skirt", + "opentrons_flex_deck_riser", + "opentrons_tough_pcr_auto_sealing_lid", + "protocol_engine_lid_stack_object" + ], + "cornerOffsetFromSlot": { + "x": 0, + "y": 0, + "z": -0.71 + }, + "dimensions": { + "xDimension": 127.7, + "yDimension": 85.48, + "zDimension": 12.8 + }, + "gripForce": 15.0, + "gripHeightFromLabwareBottom": 7.91, + "gripperOffsets": { + "default": { + "dropOffset": { + "x": 0, + "y": 0.52, + "z": -6 + }, + "pickUpOffset": { + "x": 0, + "y": 0, + "z": 1.5 + } + }, + "lidDisposalOffsets": { + "dropOffset": { + "x": 0, + "y": 5.0, + "z": 50.0 + }, + "pickUpOffset": { + "x": 0, + "y": 0, + "z": 0 + } + }, + "lidOffsets": { + "dropOffset": { + "x": 0.5, + "y": 0, + "z": -1 + }, + "pickUpOffset": { + "x": 0.5, + "y": 0, + "z": -5 + } + } + }, + "groups": [ + { + "metadata": {}, + "wells": [] + } + ], + "metadata": { + "displayCategory": "lid", + "displayName": "Opentrons Tough PCR Auto-Sealing Lid", + "displayVolumeUnits": "µL", + "tags": [] + }, + "namespace": "opentrons", + "ordering": [], + "parameters": { + "format": "irregular", + "isMagneticModuleCompatible": false, + "isTiprack": false, + "loadName": "opentrons_tough_pcr_auto_sealing_lid", + "quirks": [] + }, + "schemaVersion": 3, + "stackLimit": 5, + "stackingOffsetWithLabware": { + "armadillo_96_wellplate_200ul_pcr_full_skirt": { + "x": 0, + "y": 0, + "z": 8.193 + }, + "biorad_96_wellplate_200ul_pcr": { + "x": 0, + "y": 0, + "z": 8.08 + }, + "default": { + "x": 0, + "y": 0, + "z": 8.193 + }, + "opentrons_96_wellplate_200ul_pcr_full_skirt": { + "x": 0, + "y": 0, + "z": 8.193 + }, + "opentrons_flex_deck_riser": { + "x": 0, + "y": 0, + "z": 34 + }, + "opentrons_tough_pcr_auto_sealing_lid": { + "x": 0, + "y": 0, + "z": 6.492 + }, + "protocol_engine_lid_stack_object": { + "x": 0, + "y": 0, + "z": 0 + } + }, + "stackingOffsetWithModule": { + "thermocyclerModuleV2": { + "x": 0, + "y": 0, + "z": 0 + } + }, + "version": 1, + "wells": {} + }, + "labwareId": "UUID" + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "loadLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "5a0196883a2bd94fe59741103a03ca9f", + "notes": [], + "params": { + "loadName": "opentrons_tough_pcr_auto_sealing_lid", + "location": { + "labwareId": "UUID" + }, + "namespace": "opentrons", + "version": 1 + }, + "result": { + "definition": { + "allowedRoles": [ + "labware", + "lid" + ], + "brand": { + "brand": "Opentrons", + "brandId": [] + }, + "compatibleParentLabware": [ + "armadillo_96_wellplate_200ul_pcr_full_skirt", + "biorad_96_wellplate_200ul_pcr", + "opentrons_96_wellplate_200ul_pcr_full_skirt", + "opentrons_flex_deck_riser", + "opentrons_tough_pcr_auto_sealing_lid", + "protocol_engine_lid_stack_object" + ], + "cornerOffsetFromSlot": { + "x": 0, + "y": 0, + "z": -0.71 + }, + "dimensions": { + "xDimension": 127.7, + "yDimension": 85.48, + "zDimension": 12.8 + }, + "gripForce": 15.0, + "gripHeightFromLabwareBottom": 7.91, + "gripperOffsets": { + "default": { + "dropOffset": { + "x": 0, + "y": 0.52, + "z": -6 + }, + "pickUpOffset": { + "x": 0, + "y": 0, + "z": 1.5 + } + }, + "lidDisposalOffsets": { + "dropOffset": { + "x": 0, + "y": 5.0, + "z": 50.0 + }, + "pickUpOffset": { + "x": 0, + "y": 0, + "z": 0 + } + }, + "lidOffsets": { + "dropOffset": { + "x": 0.5, + "y": 0, + "z": -1 + }, + "pickUpOffset": { + "x": 0.5, + "y": 0, + "z": -5 + } + } + }, + "groups": [ + { + "metadata": {}, + "wells": [] + } + ], + "metadata": { + "displayCategory": "lid", + "displayName": "Opentrons Tough PCR Auto-Sealing Lid", + "displayVolumeUnits": "µL", + "tags": [] + }, + "namespace": "opentrons", + "ordering": [], + "parameters": { + "format": "irregular", + "isMagneticModuleCompatible": false, + "isTiprack": false, + "loadName": "opentrons_tough_pcr_auto_sealing_lid", + "quirks": [] + }, + "schemaVersion": 3, + "stackLimit": 5, + "stackingOffsetWithLabware": { + "armadillo_96_wellplate_200ul_pcr_full_skirt": { + "x": 0, + "y": 0, + "z": 8.193 + }, + "biorad_96_wellplate_200ul_pcr": { + "x": 0, + "y": 0, + "z": 8.08 + }, + "default": { + "x": 0, + "y": 0, + "z": 8.193 + }, + "opentrons_96_wellplate_200ul_pcr_full_skirt": { + "x": 0, + "y": 0, + "z": 8.193 + }, + "opentrons_flex_deck_riser": { + "x": 0, + "y": 0, + "z": 34 + }, + "opentrons_tough_pcr_auto_sealing_lid": { + "x": 0, + "y": 0, + "z": 6.492 + }, + "protocol_engine_lid_stack_object": { + "x": 0, + "y": 0, + "z": 0 + } + }, + "stackingOffsetWithModule": { + "thermocyclerModuleV2": { + "x": 0, + "y": 0, + "z": 0 + } + }, + "version": 1, + "wells": {} + }, + "labwareId": "UUID" + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "loadLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "cbf8207de879666929089ae9482deb18", + "notes": [], + "params": { + "loadName": "opentrons_tough_pcr_auto_sealing_lid", + "location": { + "labwareId": "UUID" + }, + "namespace": "opentrons", + "version": 1 + }, + "result": { + "definition": { + "allowedRoles": [ + "labware", + "lid" + ], + "brand": { + "brand": "Opentrons", + "brandId": [] + }, + "compatibleParentLabware": [ + "armadillo_96_wellplate_200ul_pcr_full_skirt", + "biorad_96_wellplate_200ul_pcr", + "opentrons_96_wellplate_200ul_pcr_full_skirt", + "opentrons_flex_deck_riser", + "opentrons_tough_pcr_auto_sealing_lid", + "protocol_engine_lid_stack_object" + ], + "cornerOffsetFromSlot": { + "x": 0, + "y": 0, + "z": -0.71 + }, + "dimensions": { + "xDimension": 127.7, + "yDimension": 85.48, + "zDimension": 12.8 + }, + "gripForce": 15.0, + "gripHeightFromLabwareBottom": 7.91, + "gripperOffsets": { + "default": { + "dropOffset": { + "x": 0, + "y": 0.52, + "z": -6 + }, + "pickUpOffset": { + "x": 0, + "y": 0, + "z": 1.5 + } + }, + "lidDisposalOffsets": { + "dropOffset": { + "x": 0, + "y": 5.0, + "z": 50.0 + }, + "pickUpOffset": { + "x": 0, + "y": 0, + "z": 0 + } + }, + "lidOffsets": { + "dropOffset": { + "x": 0.5, + "y": 0, + "z": -1 + }, + "pickUpOffset": { + "x": 0.5, + "y": 0, + "z": -5 + } + } + }, + "groups": [ + { + "metadata": {}, + "wells": [] + } + ], + "metadata": { + "displayCategory": "lid", + "displayName": "Opentrons Tough PCR Auto-Sealing Lid", + "displayVolumeUnits": "µL", + "tags": [] + }, + "namespace": "opentrons", + "ordering": [], + "parameters": { + "format": "irregular", + "isMagneticModuleCompatible": false, + "isTiprack": false, + "loadName": "opentrons_tough_pcr_auto_sealing_lid", + "quirks": [] + }, + "schemaVersion": 3, + "stackLimit": 5, + "stackingOffsetWithLabware": { + "armadillo_96_wellplate_200ul_pcr_full_skirt": { + "x": 0, + "y": 0, + "z": 8.193 + }, + "biorad_96_wellplate_200ul_pcr": { + "x": 0, + "y": 0, + "z": 8.08 + }, + "default": { + "x": 0, + "y": 0, + "z": 8.193 + }, + "opentrons_96_wellplate_200ul_pcr_full_skirt": { + "x": 0, + "y": 0, + "z": 8.193 + }, + "opentrons_flex_deck_riser": { + "x": 0, + "y": 0, + "z": 34 + }, + "opentrons_tough_pcr_auto_sealing_lid": { + "x": 0, + "y": 0, + "z": 6.492 + }, + "protocol_engine_lid_stack_object": { + "x": 0, + "y": 0, + "z": 0 + } + }, + "stackingOffsetWithModule": { + "thermocyclerModuleV2": { + "x": 0, + "y": 0, + "z": 0 + } + }, + "version": 1, + "wells": {} + }, + "labwareId": "UUID" + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "loadLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "7708b9b51c3e7b6afd7abae3a8fe5a3d", + "notes": [], + "params": { + "loadName": "opentrons_tough_pcr_auto_sealing_lid", + "location": { + "labwareId": "UUID" + }, + "namespace": "opentrons", + "version": 1 + }, + "result": { + "definition": { + "allowedRoles": [ + "labware", + "lid" + ], + "brand": { + "brand": "Opentrons", + "brandId": [] + }, + "compatibleParentLabware": [ + "armadillo_96_wellplate_200ul_pcr_full_skirt", + "biorad_96_wellplate_200ul_pcr", + "opentrons_96_wellplate_200ul_pcr_full_skirt", + "opentrons_flex_deck_riser", + "opentrons_tough_pcr_auto_sealing_lid", + "protocol_engine_lid_stack_object" + ], + "cornerOffsetFromSlot": { + "x": 0, + "y": 0, + "z": -0.71 + }, + "dimensions": { + "xDimension": 127.7, + "yDimension": 85.48, + "zDimension": 12.8 + }, + "gripForce": 15.0, + "gripHeightFromLabwareBottom": 7.91, + "gripperOffsets": { + "default": { + "dropOffset": { + "x": 0, + "y": 0.52, + "z": -6 + }, + "pickUpOffset": { + "x": 0, + "y": 0, + "z": 1.5 + } + }, + "lidDisposalOffsets": { + "dropOffset": { + "x": 0, + "y": 5.0, + "z": 50.0 + }, + "pickUpOffset": { + "x": 0, + "y": 0, + "z": 0 + } + }, + "lidOffsets": { + "dropOffset": { + "x": 0.5, + "y": 0, + "z": -1 + }, + "pickUpOffset": { + "x": 0.5, + "y": 0, + "z": -5 + } + } + }, + "groups": [ + { + "metadata": {}, + "wells": [] + } + ], + "metadata": { + "displayCategory": "lid", + "displayName": "Opentrons Tough PCR Auto-Sealing Lid", + "displayVolumeUnits": "µL", + "tags": [] + }, + "namespace": "opentrons", + "ordering": [], + "parameters": { + "format": "irregular", + "isMagneticModuleCompatible": false, + "isTiprack": false, + "loadName": "opentrons_tough_pcr_auto_sealing_lid", + "quirks": [] + }, + "schemaVersion": 3, + "stackLimit": 5, + "stackingOffsetWithLabware": { + "armadillo_96_wellplate_200ul_pcr_full_skirt": { + "x": 0, + "y": 0, + "z": 8.193 + }, + "biorad_96_wellplate_200ul_pcr": { + "x": 0, + "y": 0, + "z": 8.08 + }, + "default": { + "x": 0, + "y": 0, + "z": 8.193 + }, + "opentrons_96_wellplate_200ul_pcr_full_skirt": { + "x": 0, + "y": 0, + "z": 8.193 + }, + "opentrons_flex_deck_riser": { + "x": 0, + "y": 0, + "z": 34 + }, + "opentrons_tough_pcr_auto_sealing_lid": { + "x": 0, + "y": 0, + "z": 6.492 + }, + "protocol_engine_lid_stack_object": { + "x": 0, + "y": 0, + "z": 0 + } + }, + "stackingOffsetWithModule": { + "thermocyclerModuleV2": { + "x": 0, + "y": 0, + "z": 0 + } + }, + "version": 1, + "wells": {} + }, + "labwareId": "UUID" + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "thermocycler/openLid", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "16babbcf08868f1cd390f15f6382d439", + "notes": [], + "params": { + "moduleId": "UUID" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "heaterShaker/openLabwareLatch", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "1724a4af6ae0b4a1dd1d4a3bb979f2d9", + "notes": [], + "params": { + "moduleId": "UUID" + }, + "result": { + "pipetteRetracted": true + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "absorbanceReader/closeLid", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "1ca1ef496f94bdf2144e768ec088247a", + "notes": [], + "params": { + "moduleId": "UUID" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "absorbanceReader/initialize", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "457f0a0dfd866c188afdebdce5f2d1d2", + "notes": [], + "params": { + "measureMode": "single", + "moduleId": "UUID", + "referenceWavelength": 450, + "sampleWavelengths": [ + 600 + ] + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "absorbanceReader/openLid", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "cbedce386d6e0b1601924fe05f360e4a", + "notes": [], + "params": { + "moduleId": "UUID" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "loadLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "e234d87c59112fd9ea52cf83d3242171", + "notes": [], + "params": { + "loadName": "opentrons_96_well_aluminum_block", + "location": { + "moduleId": "UUID" + }, + "namespace": "opentrons", + "version": 1 + }, + "result": { + "definition": { + "allowedRoles": [ + "adapter" + ], + "brand": { + "brand": "Opentrons", + "brandId": [] + }, + "cornerOffsetFromSlot": { + "x": 0, + "y": 0, + "z": 0 + }, + "dimensions": { + "xDimension": 127.76, + "yDimension": 85.48, + "zDimension": 18.16 + }, + "gripperOffsets": { + "default": { + "dropOffset": { + "x": 0, + "y": 0, + "z": 1.0 + }, + "pickUpOffset": { + "x": 0, + "y": 0, + "z": 0 + } + } + }, + "groups": [ + { + "metadata": { + "wellBottomShape": "v" + }, + "wells": [ + "A1", + "A10", + "A11", + "A12", + "A2", + "A3", + "A4", + "A5", + "A6", + "A7", + "A8", + "A9", + "B1", + "B10", + "B11", + "B12", + "B2", + "B3", + "B4", + "B5", + "B6", + "B7", + "B8", + "B9", + "C1", + "C10", + "C11", + "C12", + "C2", + "C3", + "C4", + "C5", + "C6", + "C7", + "C8", + "C9", + "D1", + "D10", + "D11", + "D12", + "D2", + "D3", + "D4", + "D5", + "D6", + "D7", + "D8", + "D9", + "E1", + "E10", + "E11", + "E12", + "E2", + "E3", + "E4", + "E5", + "E6", + "E7", + "E8", + "E9", + "F1", + "F10", + "F11", + "F12", + "F2", + "F3", + "F4", + "F5", + "F6", + "F7", + "F8", + "F9", + "G1", + "G10", + "G11", + "G12", + "G2", + "G3", + "G4", + "G5", + "G6", + "G7", + "G8", + "G9", + "H1", + "H10", + "H11", + "H12", + "H2", + "H3", + "H4", + "H5", + "H6", + "H7", + "H8", + "H9" + ] + } + ], + "metadata": { + "displayCategory": "aluminumBlock", + "displayName": "Opentrons 96 Well Aluminum Block", + "displayVolumeUnits": "µL", + "tags": [] + }, + "namespace": "opentrons", + "ordering": [ + [ + "A1", + "B1", + "C1", + "D1", + "E1", + "F1", + "G1", + "H1" + ], + [ + "A10", + "B10", + "C10", + "D10", + "E10", + "F10", + "G10", + "H10" + ], + [ + "A11", + "B11", + "C11", + "D11", + "E11", + "F11", + "G11", + "H11" + ], + [ + "A12", + "B12", + "C12", + "D12", + "E12", + "F12", + "G12", + "H12" + ], + [ + "A2", + "B2", + "C2", + "D2", + "E2", + "F2", + "G2", + "H2" + ], + [ + "A3", + "B3", + "C3", + "D3", + "E3", + "F3", + "G3", + "H3" + ], + [ + "A4", + "B4", + "C4", + "D4", + "E4", + "F4", + "G4", + "H4" + ], + [ + "A5", + "B5", + "C5", + "D5", + "E5", + "F5", + "G5", + "H5" + ], + [ + "A6", + "B6", + "C6", + "D6", + "E6", + "F6", + "G6", + "H6" + ], + [ + "A7", + "B7", + "C7", + "D7", + "E7", + "F7", + "G7", + "H7" + ], + [ + "A8", + "B8", + "C8", + "D8", + "E8", + "F8", + "G8", + "H8" + ], + [ + "A9", + "B9", + "C9", + "D9", + "E9", + "F9", + "G9", + "H9" + ] + ], + "parameters": { + "format": "96Standard", + "isMagneticModuleCompatible": false, + "isTiprack": false, + "loadName": "opentrons_96_well_aluminum_block", + "quirks": [] + }, + "schemaVersion": 2, + "stackingOffsetWithLabware": {}, + "stackingOffsetWithModule": {}, + "version": 1, + "wells": { + "A1": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 14.38, + "y": 74.24, + "z": 3.38 + }, + "A10": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 95.38, + "y": 74.24, + "z": 3.38 + }, + "A11": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 104.38, + "y": 74.24, + "z": 3.38 + }, + "A12": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 113.38, + "y": 74.24, + "z": 3.38 + }, + "A2": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 23.38, + "y": 74.24, + "z": 3.38 + }, + "A3": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 32.38, + "y": 74.24, + "z": 3.38 + }, + "A4": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 41.38, + "y": 74.24, + "z": 3.38 + }, + "A5": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 50.38, + "y": 74.24, + "z": 3.38 + }, + "A6": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 59.38, + "y": 74.24, + "z": 3.38 + }, + "A7": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 68.38, + "y": 74.24, + "z": 3.38 + }, + "A8": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 77.38, + "y": 74.24, + "z": 3.38 + }, + "A9": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 86.38, + "y": 74.24, + "z": 3.38 + }, + "B1": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 14.38, + "y": 65.24, + "z": 3.38 + }, + "B10": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 95.38, + "y": 65.24, + "z": 3.38 + }, + "B11": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 104.38, + "y": 65.24, + "z": 3.38 + }, + "B12": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 113.38, + "y": 65.24, + "z": 3.38 + }, + "B2": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 23.38, + "y": 65.24, + "z": 3.38 + }, + "B3": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 32.38, + "y": 65.24, + "z": 3.38 + }, + "B4": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 41.38, + "y": 65.24, + "z": 3.38 + }, + "B5": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 50.38, + "y": 65.24, + "z": 3.38 + }, + "B6": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 59.38, + "y": 65.24, + "z": 3.38 + }, + "B7": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 68.38, + "y": 65.24, + "z": 3.38 + }, + "B8": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 77.38, + "y": 65.24, + "z": 3.38 + }, + "B9": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 86.38, + "y": 65.24, + "z": 3.38 + }, + "C1": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 14.38, + "y": 56.24, + "z": 3.38 + }, + "C10": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 95.38, + "y": 56.24, + "z": 3.38 + }, + "C11": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 104.38, + "y": 56.24, + "z": 3.38 + }, + "C12": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 113.38, + "y": 56.24, + "z": 3.38 + }, + "C2": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 23.38, + "y": 56.24, + "z": 3.38 + }, + "C3": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 32.38, + "y": 56.24, + "z": 3.38 + }, + "C4": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 41.38, + "y": 56.24, + "z": 3.38 + }, + "C5": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 50.38, + "y": 56.24, + "z": 3.38 + }, + "C6": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 59.38, + "y": 56.24, + "z": 3.38 + }, + "C7": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 68.38, + "y": 56.24, + "z": 3.38 + }, + "C8": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 77.38, + "y": 56.24, + "z": 3.38 + }, + "C9": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 86.38, + "y": 56.24, + "z": 3.38 + }, + "D1": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 14.38, + "y": 47.24, + "z": 3.38 + }, + "D10": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 95.38, + "y": 47.24, + "z": 3.38 + }, + "D11": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 104.38, + "y": 47.24, + "z": 3.38 + }, + "D12": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 113.38, + "y": 47.24, + "z": 3.38 + }, + "D2": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 23.38, + "y": 47.24, + "z": 3.38 + }, + "D3": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 32.38, + "y": 47.24, + "z": 3.38 + }, + "D4": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 41.38, + "y": 47.24, + "z": 3.38 + }, + "D5": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 50.38, + "y": 47.24, + "z": 3.38 + }, + "D6": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 59.38, + "y": 47.24, + "z": 3.38 + }, + "D7": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 68.38, + "y": 47.24, + "z": 3.38 + }, + "D8": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 77.38, + "y": 47.24, + "z": 3.38 + }, + "D9": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 86.38, + "y": 47.24, + "z": 3.38 + }, + "E1": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 14.38, + "y": 38.24, + "z": 3.38 + }, + "E10": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 95.38, + "y": 38.24, + "z": 3.38 + }, + "E11": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 104.38, + "y": 38.24, + "z": 3.38 + }, + "E12": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 113.38, + "y": 38.24, + "z": 3.38 + }, + "E2": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 23.38, + "y": 38.24, + "z": 3.38 + }, + "E3": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 32.38, + "y": 38.24, + "z": 3.38 + }, + "E4": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 41.38, + "y": 38.24, + "z": 3.38 + }, + "E5": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 50.38, + "y": 38.24, + "z": 3.38 + }, + "E6": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 59.38, + "y": 38.24, + "z": 3.38 + }, + "E7": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 68.38, + "y": 38.24, + "z": 3.38 + }, + "E8": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 77.38, + "y": 38.24, + "z": 3.38 + }, + "E9": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 86.38, + "y": 38.24, + "z": 3.38 + }, + "F1": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 14.38, + "y": 29.24, + "z": 3.38 + }, + "F10": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 95.38, + "y": 29.24, + "z": 3.38 + }, + "F11": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 104.38, + "y": 29.24, + "z": 3.38 + }, + "F12": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 113.38, + "y": 29.24, + "z": 3.38 + }, + "F2": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 23.38, + "y": 29.24, + "z": 3.38 + }, + "F3": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 32.38, + "y": 29.24, + "z": 3.38 + }, + "F4": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 41.38, + "y": 29.24, + "z": 3.38 + }, + "F5": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 50.38, + "y": 29.24, + "z": 3.38 + }, + "F6": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 59.38, + "y": 29.24, + "z": 3.38 + }, + "F7": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 68.38, + "y": 29.24, + "z": 3.38 + }, + "F8": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 77.38, + "y": 29.24, + "z": 3.38 + }, + "F9": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 86.38, + "y": 29.24, + "z": 3.38 + }, + "G1": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 14.38, + "y": 20.24, + "z": 3.38 + }, + "G10": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 95.38, + "y": 20.24, + "z": 3.38 + }, + "G11": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 104.38, + "y": 20.24, + "z": 3.38 + }, + "G12": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 113.38, + "y": 20.24, + "z": 3.38 + }, + "G2": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 23.38, + "y": 20.24, + "z": 3.38 + }, + "G3": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 32.38, + "y": 20.24, + "z": 3.38 + }, + "G4": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 41.38, + "y": 20.24, + "z": 3.38 + }, + "G5": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 50.38, + "y": 20.24, + "z": 3.38 + }, + "G6": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 59.38, + "y": 20.24, + "z": 3.38 + }, + "G7": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 68.38, + "y": 20.24, + "z": 3.38 + }, + "G8": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 77.38, + "y": 20.24, + "z": 3.38 + }, + "G9": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 86.38, + "y": 20.24, + "z": 3.38 + }, + "H1": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 14.38, + "y": 11.24, + "z": 3.38 + }, + "H10": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 95.38, + "y": 11.24, + "z": 3.38 + }, + "H11": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 104.38, + "y": 11.24, + "z": 3.38 + }, + "H12": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 113.38, + "y": 11.24, + "z": 3.38 + }, + "H2": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 23.38, + "y": 11.24, + "z": 3.38 + }, + "H3": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 32.38, + "y": 11.24, + "z": 3.38 + }, + "H4": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 41.38, + "y": 11.24, + "z": 3.38 + }, + "H5": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 50.38, + "y": 11.24, + "z": 3.38 + }, + "H6": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 59.38, + "y": 11.24, + "z": 3.38 + }, + "H7": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 68.38, + "y": 11.24, + "z": 3.38 + }, + "H8": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 77.38, + "y": 11.24, + "z": 3.38 + }, + "H9": { + "depth": 14.78, + "diameter": 5.34, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 86.38, + "y": 11.24, + "z": 3.38 + } + } + }, + "labwareId": "UUID" + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "loadLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "2b9be36c72ca44069f3f7e9b4836f345", + "notes": [], + "params": { + "loadName": "opentrons_96_pcr_adapter", + "location": { + "moduleId": "UUID" + }, + "namespace": "opentrons", + "version": 1 + }, + "result": { + "definition": { + "allowedRoles": [ + "adapter" + ], + "brand": { + "brand": "Opentrons", + "brandId": [] + }, + "cornerOffsetFromSlot": { + "x": 8.5, + "y": 5.5, + "z": 0 + }, + "dimensions": { + "xDimension": 111, + "yDimension": 75, + "zDimension": 13.85 + }, + "gripperOffsets": { + "default": { + "dropOffset": { + "x": 0, + "y": 0, + "z": 1.0 + }, + "pickUpOffset": { + "x": 0, + "y": 0, + "z": 0 + } + } + }, + "groups": [ + { + "metadata": { + "wellBottomShape": "v" + }, + "wells": [ + "A1", + "A10", + "A11", + "A12", + "A2", + "A3", + "A4", + "A5", + "A6", + "A7", + "A8", + "A9", + "B1", + "B10", + "B11", + "B12", + "B2", + "B3", + "B4", + "B5", + "B6", + "B7", + "B8", + "B9", + "C1", + "C10", + "C11", + "C12", + "C2", + "C3", + "C4", + "C5", + "C6", + "C7", + "C8", + "C9", + "D1", + "D10", + "D11", + "D12", + "D2", + "D3", + "D4", + "D5", + "D6", + "D7", + "D8", + "D9", + "E1", + "E10", + "E11", + "E12", + "E2", + "E3", + "E4", + "E5", + "E6", + "E7", + "E8", + "E9", + "F1", + "F10", + "F11", + "F12", + "F2", + "F3", + "F4", + "F5", + "F6", + "F7", + "F8", + "F9", + "G1", + "G10", + "G11", + "G12", + "G2", + "G3", + "G4", + "G5", + "G6", + "G7", + "G8", + "G9", + "H1", + "H10", + "H11", + "H12", + "H2", + "H3", + "H4", + "H5", + "H6", + "H7", + "H8", + "H9" + ] + } + ], + "metadata": { + "displayCategory": "adapter", + "displayName": "Opentrons 96 PCR Heater-Shaker Adapter", + "displayVolumeUnits": "µL", + "tags": [] + }, + "namespace": "opentrons", + "ordering": [ + [ + "A1", + "B1", + "C1", + "D1", + "E1", + "F1", + "G1", + "H1" + ], + [ + "A10", + "B10", + "C10", + "D10", + "E10", + "F10", + "G10", + "H10" + ], + [ + "A11", + "B11", + "C11", + "D11", + "E11", + "F11", + "G11", + "H11" + ], + [ + "A12", + "B12", + "C12", + "D12", + "E12", + "F12", + "G12", + "H12" + ], + [ + "A2", + "B2", + "C2", + "D2", + "E2", + "F2", + "G2", + "H2" + ], + [ + "A3", + "B3", + "C3", + "D3", + "E3", + "F3", + "G3", + "H3" + ], + [ + "A4", + "B4", + "C4", + "D4", + "E4", + "F4", + "G4", + "H4" + ], + [ + "A5", + "B5", + "C5", + "D5", + "E5", + "F5", + "G5", + "H5" + ], + [ + "A6", + "B6", + "C6", + "D6", + "E6", + "F6", + "G6", + "H6" + ], + [ + "A7", + "B7", + "C7", + "D7", + "E7", + "F7", + "G7", + "H7" + ], + [ + "A8", + "B8", + "C8", + "D8", + "E8", + "F8", + "G8", + "H8" + ], + [ + "A9", + "B9", + "C9", + "D9", + "E9", + "F9", + "G9", + "H9" + ] + ], + "parameters": { + "format": "96Standard", + "isMagneticModuleCompatible": false, + "isTiprack": false, + "loadName": "opentrons_96_pcr_adapter", + "quirks": [] + }, + "schemaVersion": 2, + "stackingOffsetWithLabware": {}, + "stackingOffsetWithModule": {}, + "version": 1, + "wells": { + "A1": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 6, + "y": 69, + "z": 1.85 + }, + "A10": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 87, + "y": 69, + "z": 1.85 + }, + "A11": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 96, + "y": 69, + "z": 1.85 + }, + "A12": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 105, + "y": 69, + "z": 1.85 + }, + "A2": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 15, + "y": 69, + "z": 1.85 + }, + "A3": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 24, + "y": 69, + "z": 1.85 + }, + "A4": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 33, + "y": 69, + "z": 1.85 + }, + "A5": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 42, + "y": 69, + "z": 1.85 + }, + "A6": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 51, + "y": 69, + "z": 1.85 + }, + "A7": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 60, + "y": 69, + "z": 1.85 + }, + "A8": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 69, + "y": 69, + "z": 1.85 + }, + "A9": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 78, + "y": 69, + "z": 1.85 + }, + "B1": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 6, + "y": 60, + "z": 1.85 + }, + "B10": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 87, + "y": 60, + "z": 1.85 + }, + "B11": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 96, + "y": 60, + "z": 1.85 + }, + "B12": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 105, + "y": 60, + "z": 1.85 + }, + "B2": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 15, + "y": 60, + "z": 1.85 + }, + "B3": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 24, + "y": 60, + "z": 1.85 + }, + "B4": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 33, + "y": 60, + "z": 1.85 + }, + "B5": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 42, + "y": 60, + "z": 1.85 + }, + "B6": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 51, + "y": 60, + "z": 1.85 + }, + "B7": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 60, + "y": 60, + "z": 1.85 + }, + "B8": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 69, + "y": 60, + "z": 1.85 + }, + "B9": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 78, + "y": 60, + "z": 1.85 + }, + "C1": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 6, + "y": 51, + "z": 1.85 + }, + "C10": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 87, + "y": 51, + "z": 1.85 + }, + "C11": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 96, + "y": 51, + "z": 1.85 + }, + "C12": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 105, + "y": 51, + "z": 1.85 + }, + "C2": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 15, + "y": 51, + "z": 1.85 + }, + "C3": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 24, + "y": 51, + "z": 1.85 + }, + "C4": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 33, + "y": 51, + "z": 1.85 + }, + "C5": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 42, + "y": 51, + "z": 1.85 + }, + "C6": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 51, + "y": 51, + "z": 1.85 + }, + "C7": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 60, + "y": 51, + "z": 1.85 + }, + "C8": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 69, + "y": 51, + "z": 1.85 + }, + "C9": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 78, + "y": 51, + "z": 1.85 + }, + "D1": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 6, + "y": 42, + "z": 1.85 + }, + "D10": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 87, + "y": 42, + "z": 1.85 + }, + "D11": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 96, + "y": 42, + "z": 1.85 + }, + "D12": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 105, + "y": 42, + "z": 1.85 + }, + "D2": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 15, + "y": 42, + "z": 1.85 + }, + "D3": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 24, + "y": 42, + "z": 1.85 + }, + "D4": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 33, + "y": 42, + "z": 1.85 + }, + "D5": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 42, + "y": 42, + "z": 1.85 + }, + "D6": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 51, + "y": 42, + "z": 1.85 + }, + "D7": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 60, + "y": 42, + "z": 1.85 + }, + "D8": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 69, + "y": 42, + "z": 1.85 + }, + "D9": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 78, + "y": 42, + "z": 1.85 + }, + "E1": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 6, + "y": 33, + "z": 1.85 + }, + "E10": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 87, + "y": 33, + "z": 1.85 + }, + "E11": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 96, + "y": 33, + "z": 1.85 + }, + "E12": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 105, + "y": 33, + "z": 1.85 + }, + "E2": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 15, + "y": 33, + "z": 1.85 + }, + "E3": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 24, + "y": 33, + "z": 1.85 + }, + "E4": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 33, + "y": 33, + "z": 1.85 + }, + "E5": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 42, + "y": 33, + "z": 1.85 + }, + "E6": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 51, + "y": 33, + "z": 1.85 + }, + "E7": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 60, + "y": 33, + "z": 1.85 + }, + "E8": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 69, + "y": 33, + "z": 1.85 + }, + "E9": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 78, + "y": 33, + "z": 1.85 + }, + "F1": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 6, + "y": 24, + "z": 1.85 + }, + "F10": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 87, + "y": 24, + "z": 1.85 + }, + "F11": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 96, + "y": 24, + "z": 1.85 + }, + "F12": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 105, + "y": 24, + "z": 1.85 + }, + "F2": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 15, + "y": 24, + "z": 1.85 + }, + "F3": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 24, + "y": 24, + "z": 1.85 + }, + "F4": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 33, + "y": 24, + "z": 1.85 + }, + "F5": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 42, + "y": 24, + "z": 1.85 + }, + "F6": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 51, + "y": 24, + "z": 1.85 + }, + "F7": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 60, + "y": 24, + "z": 1.85 + }, + "F8": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 69, + "y": 24, + "z": 1.85 + }, + "F9": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 78, + "y": 24, + "z": 1.85 + }, + "G1": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 6, + "y": 15, + "z": 1.85 + }, + "G10": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 87, + "y": 15, + "z": 1.85 + }, + "G11": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 96, + "y": 15, + "z": 1.85 + }, + "G12": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 105, + "y": 15, + "z": 1.85 + }, + "G2": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 15, + "y": 15, + "z": 1.85 + }, + "G3": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 24, + "y": 15, + "z": 1.85 + }, + "G4": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 33, + "y": 15, + "z": 1.85 + }, + "G5": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 42, + "y": 15, + "z": 1.85 + }, + "G6": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 51, + "y": 15, + "z": 1.85 + }, + "G7": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 60, + "y": 15, + "z": 1.85 + }, + "G8": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 69, + "y": 15, + "z": 1.85 + }, + "G9": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 78, + "y": 15, + "z": 1.85 + }, + "H1": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 6, + "y": 6, + "z": 1.85 + }, + "H10": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 87, + "y": 6, + "z": 1.85 + }, + "H11": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 96, + "y": 6, + "z": 1.85 + }, + "H12": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 105, + "y": 6, + "z": 1.85 + }, + "H2": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 15, + "y": 6, + "z": 1.85 + }, + "H3": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 24, + "y": 6, + "z": 1.85 + }, + "H4": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 33, + "y": 6, + "z": 1.85 + }, + "H5": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 42, + "y": 6, + "z": 1.85 + }, + "H6": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 51, + "y": 6, + "z": 1.85 + }, + "H7": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 60, + "y": 6, + "z": 1.85 + }, + "H8": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 69, + "y": 6, + "z": 1.85 + }, + "H9": { + "depth": 12, + "diameter": 5.64, + "shape": "circular", + "totalLiquidVolume": 0, + "x": 78, + "y": 6, + "z": 1.85 + } + } + }, + "labwareId": "UUID" + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "loadLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "507480a9ad4e135e7a7d36ffd6d2d8e6", + "notes": [], + "params": { + "loadName": "nest_1_reservoir_290ml", + "location": { + "slotName": "D2" + }, + "namespace": "opentrons", + "version": 1 + }, + "result": { + "definition": { + "allowedRoles": [], + "brand": { + "brand": "NEST", + "brandId": [ + "360206", + "360266" + ], + "links": [ + "https://www.nest-biotech.com/reagent-reserviors" + ] + }, + "cornerOffsetFromSlot": { + "x": 0, + "y": 0, + "z": 0 + }, + "dimensions": { + "xDimension": 127.76, + "yDimension": 85.47, + "zDimension": 44.4 + }, + "gripperOffsets": {}, + "groups": [ + { + "metadata": { + "wellBottomShape": "v" + }, + "wells": [ + "A1" + ] + } + ], + "metadata": { + "displayCategory": "reservoir", + "displayName": "NEST 1 Well Reservoir 290 mL", + "displayVolumeUnits": "mL", + "tags": [] + }, + "namespace": "opentrons", + "ordering": [ + [ + "A1" + ] + ], + "parameters": { + "format": "trough", + "isMagneticModuleCompatible": false, + "isTiprack": false, + "loadName": "nest_1_reservoir_290ml", + "quirks": [ + "centerMultichannelOnWells", + "touchTipDisabled" + ] + }, + "schemaVersion": 2, + "stackingOffsetWithLabware": {}, + "stackingOffsetWithModule": {}, + "version": 1, + "wells": { + "A1": { + "depth": 39.55, + "shape": "rectangular", + "totalLiquidVolume": 290000, + "x": 63.88, + "xDimension": 106.8, + "y": 42.74, + "yDimension": 71.2, + "z": 4.85 + } + } + }, + "labwareId": "UUID" + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "loadLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "8ae6e077abe5453762e935d116fca696", + "notes": [], + "params": { + "loadName": "opentrons_96_wellplate_200ul_pcr_full_skirt", + "location": { + "slotName": "C2" + }, + "namespace": "opentrons", + "version": 2 + }, + "result": { + "definition": { + "allowedRoles": [], + "brand": { + "brand": "Opentrons", + "brandId": [ + "991-00076" + ], + "links": [ + "https://shop.opentrons.com/tough-0.2-ml-96-well-pcr-plate-full-skirt/" + ] + }, + "cornerOffsetFromSlot": { + "x": 0, + "y": 0, + "z": 0 + }, + "dimensions": { + "xDimension": 127.76, + "yDimension": 85.48, + "zDimension": 16.0 + }, + "gripForce": 15.0, + "gripHeightFromLabwareBottom": 10.0, + "gripperOffsets": {}, + "groups": [ + { + "metadata": { + "wellBottomShape": "v" + }, + "wells": [ + "A1", + "A10", + "A11", + "A12", + "A2", + "A3", + "A4", + "A5", + "A6", + "A7", + "A8", + "A9", + "B1", + "B10", + "B11", + "B12", + "B2", + "B3", + "B4", + "B5", + "B6", + "B7", + "B8", + "B9", + "C1", + "C10", + "C11", + "C12", + "C2", + "C3", + "C4", + "C5", + "C6", + "C7", + "C8", + "C9", + "D1", + "D10", + "D11", + "D12", + "D2", + "D3", + "D4", + "D5", + "D6", + "D7", + "D8", + "D9", + "E1", + "E10", + "E11", + "E12", + "E2", + "E3", + "E4", + "E5", + "E6", + "E7", + "E8", + "E9", + "F1", + "F10", + "F11", + "F12", + "F2", + "F3", + "F4", + "F5", + "F6", + "F7", + "F8", + "F9", + "G1", + "G10", + "G11", + "G12", + "G2", + "G3", + "G4", + "G5", + "G6", + "G7", + "G8", + "G9", + "H1", + "H10", + "H11", + "H12", + "H2", + "H3", + "H4", + "H5", + "H6", + "H7", + "H8", + "H9" + ] + } + ], + "metadata": { + "displayCategory": "wellPlate", + "displayName": "Opentrons Tough 96 Well Plate 200 µL PCR Full Skirt", + "displayVolumeUnits": "µL", + "tags": [] + }, + "namespace": "opentrons", + "ordering": [ + [ + "A1", + "B1", + "C1", + "D1", + "E1", + "F1", + "G1", + "H1" + ], + [ + "A10", + "B10", + "C10", + "D10", + "E10", + "F10", + "G10", + "H10" + ], + [ + "A11", + "B11", + "C11", + "D11", + "E11", + "F11", + "G11", + "H11" + ], + [ + "A12", + "B12", + "C12", + "D12", + "E12", + "F12", + "G12", + "H12" + ], + [ + "A2", + "B2", + "C2", + "D2", + "E2", + "F2", + "G2", + "H2" + ], + [ + "A3", + "B3", + "C3", + "D3", + "E3", + "F3", + "G3", + "H3" + ], + [ + "A4", + "B4", + "C4", + "D4", + "E4", + "F4", + "G4", + "H4" + ], + [ + "A5", + "B5", + "C5", + "D5", + "E5", + "F5", + "G5", + "H5" + ], + [ + "A6", + "B6", + "C6", + "D6", + "E6", + "F6", + "G6", + "H6" + ], + [ + "A7", + "B7", + "C7", + "D7", + "E7", + "F7", + "G7", + "H7" + ], + [ + "A8", + "B8", + "C8", + "D8", + "E8", + "F8", + "G8", + "H8" + ], + [ + "A9", + "B9", + "C9", + "D9", + "E9", + "F9", + "G9", + "H9" + ] + ], + "parameters": { + "format": "96Standard", + "isMagneticModuleCompatible": true, + "isTiprack": false, + "loadName": "opentrons_96_wellplate_200ul_pcr_full_skirt" + }, + "schemaVersion": 2, + "stackingOffsetWithLabware": { + "opentrons_96_pcr_adapter": { + "x": 0, + "y": 0, + "z": 10.95 + }, + "opentrons_96_well_aluminum_block": { + "x": 0, + "y": 0, + "z": 11.91 + } + }, + "stackingOffsetWithModule": { + "magneticBlockV1": { + "x": 0, + "y": 0, + "z": 3.54 + }, + "thermocyclerModuleV2": { + "x": 0, + "y": 0, + "z": 10.7 + } + }, + "version": 2, + "wells": { + "A1": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 14.38, + "y": 74.24, + "z": 1.05 + }, + "A10": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 95.38, + "y": 74.24, + "z": 1.05 + }, + "A11": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 104.38, + "y": 74.24, + "z": 1.05 + }, + "A12": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 113.38, + "y": 74.24, + "z": 1.05 + }, + "A2": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 23.38, + "y": 74.24, + "z": 1.05 + }, + "A3": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 32.38, + "y": 74.24, + "z": 1.05 + }, + "A4": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 41.38, + "y": 74.24, + "z": 1.05 + }, + "A5": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 50.38, + "y": 74.24, + "z": 1.05 + }, + "A6": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 59.38, + "y": 74.24, + "z": 1.05 + }, + "A7": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 68.38, + "y": 74.24, + "z": 1.05 + }, + "A8": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 77.38, + "y": 74.24, + "z": 1.05 + }, + "A9": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 86.38, + "y": 74.24, + "z": 1.05 + }, + "B1": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 14.38, + "y": 65.24, + "z": 1.05 + }, + "B10": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 95.38, + "y": 65.24, + "z": 1.05 + }, + "B11": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 104.38, + "y": 65.24, + "z": 1.05 + }, + "B12": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 113.38, + "y": 65.24, + "z": 1.05 + }, + "B2": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 23.38, + "y": 65.24, + "z": 1.05 + }, + "B3": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 32.38, + "y": 65.24, + "z": 1.05 + }, + "B4": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 41.38, + "y": 65.24, + "z": 1.05 + }, + "B5": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 50.38, + "y": 65.24, + "z": 1.05 + }, + "B6": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 59.38, + "y": 65.24, + "z": 1.05 + }, + "B7": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 68.38, + "y": 65.24, + "z": 1.05 + }, + "B8": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 77.38, + "y": 65.24, + "z": 1.05 + }, + "B9": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 86.38, + "y": 65.24, + "z": 1.05 + }, + "C1": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 14.38, + "y": 56.24, + "z": 1.05 + }, + "C10": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 95.38, + "y": 56.24, + "z": 1.05 + }, + "C11": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 104.38, + "y": 56.24, + "z": 1.05 + }, + "C12": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 113.38, + "y": 56.24, + "z": 1.05 + }, + "C2": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 23.38, + "y": 56.24, + "z": 1.05 + }, + "C3": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 32.38, + "y": 56.24, + "z": 1.05 + }, + "C4": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 41.38, + "y": 56.24, + "z": 1.05 + }, + "C5": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 50.38, + "y": 56.24, + "z": 1.05 + }, + "C6": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 59.38, + "y": 56.24, + "z": 1.05 + }, + "C7": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 68.38, + "y": 56.24, + "z": 1.05 + }, + "C8": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 77.38, + "y": 56.24, + "z": 1.05 + }, + "C9": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 86.38, + "y": 56.24, + "z": 1.05 + }, + "D1": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 14.38, + "y": 47.24, + "z": 1.05 + }, + "D10": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 95.38, + "y": 47.24, + "z": 1.05 + }, + "D11": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 104.38, + "y": 47.24, + "z": 1.05 + }, + "D12": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 113.38, + "y": 47.24, + "z": 1.05 + }, + "D2": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 23.38, + "y": 47.24, + "z": 1.05 + }, + "D3": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 32.38, + "y": 47.24, + "z": 1.05 + }, + "D4": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 41.38, + "y": 47.24, + "z": 1.05 + }, + "D5": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 50.38, + "y": 47.24, + "z": 1.05 + }, + "D6": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 59.38, + "y": 47.24, + "z": 1.05 + }, + "D7": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 68.38, + "y": 47.24, + "z": 1.05 + }, + "D8": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 77.38, + "y": 47.24, + "z": 1.05 + }, + "D9": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 86.38, + "y": 47.24, + "z": 1.05 + }, + "E1": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 14.38, + "y": 38.24, + "z": 1.05 + }, + "E10": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 95.38, + "y": 38.24, + "z": 1.05 + }, + "E11": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 104.38, + "y": 38.24, + "z": 1.05 + }, + "E12": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 113.38, + "y": 38.24, + "z": 1.05 + }, + "E2": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 23.38, + "y": 38.24, + "z": 1.05 + }, + "E3": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 32.38, + "y": 38.24, + "z": 1.05 + }, + "E4": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 41.38, + "y": 38.24, + "z": 1.05 + }, + "E5": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 50.38, + "y": 38.24, + "z": 1.05 + }, + "E6": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 59.38, + "y": 38.24, + "z": 1.05 + }, + "E7": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 68.38, + "y": 38.24, + "z": 1.05 + }, + "E8": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 77.38, + "y": 38.24, + "z": 1.05 + }, + "E9": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 86.38, + "y": 38.24, + "z": 1.05 + }, + "F1": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 14.38, + "y": 29.24, + "z": 1.05 + }, + "F10": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 95.38, + "y": 29.24, + "z": 1.05 + }, + "F11": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 104.38, + "y": 29.24, + "z": 1.05 + }, + "F12": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 113.38, + "y": 29.24, + "z": 1.05 + }, + "F2": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 23.38, + "y": 29.24, + "z": 1.05 + }, + "F3": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 32.38, + "y": 29.24, + "z": 1.05 + }, + "F4": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 41.38, + "y": 29.24, + "z": 1.05 + }, + "F5": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 50.38, + "y": 29.24, + "z": 1.05 + }, + "F6": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 59.38, + "y": 29.24, + "z": 1.05 + }, + "F7": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 68.38, + "y": 29.24, + "z": 1.05 + }, + "F8": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 77.38, + "y": 29.24, + "z": 1.05 + }, + "F9": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 86.38, + "y": 29.24, + "z": 1.05 + }, + "G1": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 14.38, + "y": 20.24, + "z": 1.05 + }, + "G10": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 95.38, + "y": 20.24, + "z": 1.05 + }, + "G11": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 104.38, + "y": 20.24, + "z": 1.05 + }, + "G12": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 113.38, + "y": 20.24, + "z": 1.05 + }, + "G2": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 23.38, + "y": 20.24, + "z": 1.05 + }, + "G3": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 32.38, + "y": 20.24, + "z": 1.05 + }, + "G4": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 41.38, + "y": 20.24, + "z": 1.05 + }, + "G5": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 50.38, + "y": 20.24, + "z": 1.05 + }, + "G6": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 59.38, + "y": 20.24, + "z": 1.05 + }, + "G7": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 68.38, + "y": 20.24, + "z": 1.05 + }, + "G8": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 77.38, + "y": 20.24, + "z": 1.05 + }, + "G9": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 86.38, + "y": 20.24, + "z": 1.05 + }, + "H1": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 14.38, + "y": 11.24, + "z": 1.05 + }, + "H10": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 95.38, + "y": 11.24, + "z": 1.05 + }, + "H11": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 104.38, + "y": 11.24, + "z": 1.05 + }, + "H12": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 113.38, + "y": 11.24, + "z": 1.05 + }, + "H2": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 23.38, + "y": 11.24, + "z": 1.05 + }, + "H3": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 32.38, + "y": 11.24, + "z": 1.05 + }, + "H4": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 41.38, + "y": 11.24, + "z": 1.05 + }, + "H5": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 50.38, + "y": 11.24, + "z": 1.05 + }, + "H6": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 59.38, + "y": 11.24, + "z": 1.05 + }, + "H7": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 68.38, + "y": 11.24, + "z": 1.05 + }, + "H8": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 77.38, + "y": 11.24, + "z": 1.05 + }, + "H9": { + "depth": 14.95, + "diameter": 5.5, + "shape": "circular", + "totalLiquidVolume": 200, + "x": 86.38, + "y": 11.24, + "z": 1.05 + } + } + }, + "labwareId": "UUID" + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "loadLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "8a9b3ed81e0357a321f879efe1c8bc00", + "notes": [], + "params": { + "loadName": "opentrons_flex_96_tiprack_adapter", + "location": { + "slotName": "A2" + }, + "namespace": "opentrons", + "version": 1 + }, + "result": { + "definition": { + "allowedRoles": [ + "adapter" + ], + "brand": { + "brand": "Opentrons", + "brandId": [] + }, + "cornerOffsetFromSlot": { + "x": -14.25, + "y": -3.5, + "z": 0 + }, + "dimensions": { + "xDimension": 156.5, + "yDimension": 93, + "zDimension": 132 + }, + "gripperOffsets": {}, + "groups": [ + { + "metadata": {}, + "wells": [] + } + ], + "metadata": { + "displayCategory": "adapter", + "displayName": "Opentrons Flex 96 Tip Rack Adapter", + "displayVolumeUnits": "µL", + "tags": [] + }, + "namespace": "opentrons", + "ordering": [], + "parameters": { + "format": "96Standard", + "isMagneticModuleCompatible": false, + "isTiprack": false, + "loadName": "opentrons_flex_96_tiprack_adapter", + "quirks": [ + "tiprackAdapterFor96Channel" + ] + }, + "schemaVersion": 2, + "stackingOffsetWithLabware": {}, + "stackingOffsetWithModule": {}, + "version": 1, + "wells": {} + }, + "labwareId": "UUID" + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "loadLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "a59c403d3ddb2ed94d8377fdf2d634b2", + "notes": [], + "params": { + "loadName": "opentrons_flex_96_tiprack_1000ul", + "location": { + "labwareId": "UUID" + }, + "namespace": "opentrons", + "version": 1 + }, + "result": { + "definition": { + "allowedRoles": [], + "brand": { + "brand": "Opentrons", + "brandId": [] + }, + "cornerOffsetFromSlot": { + "x": 0, + "y": 0, + "z": 0 + }, + "dimensions": { + "xDimension": 127.75, + "yDimension": 85.75, + "zDimension": 99 + }, + "gripForce": 16.0, + "gripHeightFromLabwareBottom": 23.9, + "gripperOffsets": {}, + "groups": [ + { + "metadata": {}, + "wells": [ + "A1", + "A10", + "A11", + "A12", + "A2", + "A3", + "A4", + "A5", + "A6", + "A7", + "A8", + "A9", + "B1", + "B10", + "B11", + "B12", + "B2", + "B3", + "B4", + "B5", + "B6", + "B7", + "B8", + "B9", + "C1", + "C10", + "C11", + "C12", + "C2", + "C3", + "C4", + "C5", + "C6", + "C7", + "C8", + "C9", + "D1", + "D10", + "D11", + "D12", + "D2", + "D3", + "D4", + "D5", + "D6", + "D7", + "D8", + "D9", + "E1", + "E10", + "E11", + "E12", + "E2", + "E3", + "E4", + "E5", + "E6", + "E7", + "E8", + "E9", + "F1", + "F10", + "F11", + "F12", + "F2", + "F3", + "F4", + "F5", + "F6", + "F7", + "F8", + "F9", + "G1", + "G10", + "G11", + "G12", + "G2", + "G3", + "G4", + "G5", + "G6", + "G7", + "G8", + "G9", + "H1", + "H10", + "H11", + "H12", + "H2", + "H3", + "H4", + "H5", + "H6", + "H7", + "H8", + "H9" + ] + } + ], + "metadata": { + "displayCategory": "tipRack", + "displayName": "Opentrons Flex 96 Tip Rack 1000 µL", + "displayVolumeUnits": "µL", + "tags": [] + }, + "namespace": "opentrons", + "ordering": [ + [ + "A1", + "B1", + "C1", + "D1", + "E1", + "F1", + "G1", + "H1" + ], + [ + "A10", + "B10", + "C10", + "D10", + "E10", + "F10", + "G10", + "H10" + ], + [ + "A11", + "B11", + "C11", + "D11", + "E11", + "F11", + "G11", + "H11" + ], + [ + "A12", + "B12", + "C12", + "D12", + "E12", + "F12", + "G12", + "H12" + ], + [ + "A2", + "B2", + "C2", + "D2", + "E2", + "F2", + "G2", + "H2" + ], + [ + "A3", + "B3", + "C3", + "D3", + "E3", + "F3", + "G3", + "H3" + ], + [ + "A4", + "B4", + "C4", + "D4", + "E4", + "F4", + "G4", + "H4" + ], + [ + "A5", + "B5", + "C5", + "D5", + "E5", + "F5", + "G5", + "H5" + ], + [ + "A6", + "B6", + "C6", + "D6", + "E6", + "F6", + "G6", + "H6" + ], + [ + "A7", + "B7", + "C7", + "D7", + "E7", + "F7", + "G7", + "H7" + ], + [ + "A8", + "B8", + "C8", + "D8", + "E8", + "F8", + "G8", + "H8" + ], + [ + "A9", + "B9", + "C9", + "D9", + "E9", + "F9", + "G9", + "H9" + ] + ], + "parameters": { + "format": "96Standard", + "isMagneticModuleCompatible": false, + "isTiprack": true, + "loadName": "opentrons_flex_96_tiprack_1000ul", + "quirks": [], + "tipLength": 95.6, + "tipOverlap": 10.5 + }, + "schemaVersion": 2, + "stackingOffsetWithLabware": { + "opentrons_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 121 + } + }, + "stackingOffsetWithModule": {}, + "version": 1, + "wells": { + "A1": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 74.38, + "z": 1.5 + }, + "A10": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 74.38, + "z": 1.5 + }, + "A11": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 74.38, + "z": 1.5 + }, + "A12": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 74.38, + "z": 1.5 + }, + "A2": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 74.38, + "z": 1.5 + }, + "A3": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 74.38, + "z": 1.5 + }, + "A4": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 74.38, + "z": 1.5 + }, + "A5": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 74.38, + "z": 1.5 + }, + "A6": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 74.38, + "z": 1.5 + }, + "A7": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 74.38, + "z": 1.5 + }, + "A8": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 74.38, + "z": 1.5 + }, + "A9": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 74.38, + "z": 1.5 + }, + "B1": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 65.38, + "z": 1.5 + }, + "B10": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 65.38, + "z": 1.5 + }, + "B11": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 65.38, + "z": 1.5 + }, + "B12": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 65.38, + "z": 1.5 + }, + "B2": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 65.38, + "z": 1.5 + }, + "B3": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 65.38, + "z": 1.5 + }, + "B4": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 65.38, + "z": 1.5 + }, + "B5": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 65.38, + "z": 1.5 + }, + "B6": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 65.38, + "z": 1.5 + }, + "B7": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 65.38, + "z": 1.5 + }, + "B8": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 65.38, + "z": 1.5 + }, + "B9": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 65.38, + "z": 1.5 + }, + "C1": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 56.38, + "z": 1.5 + }, + "C10": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 56.38, + "z": 1.5 + }, + "C11": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 56.38, + "z": 1.5 + }, + "C12": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 56.38, + "z": 1.5 + }, + "C2": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 56.38, + "z": 1.5 + }, + "C3": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 56.38, + "z": 1.5 + }, + "C4": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 56.38, + "z": 1.5 + }, + "C5": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 56.38, + "z": 1.5 + }, + "C6": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 56.38, + "z": 1.5 + }, + "C7": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 56.38, + "z": 1.5 + }, + "C8": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 56.38, + "z": 1.5 + }, + "C9": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 56.38, + "z": 1.5 + }, + "D1": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 47.38, + "z": 1.5 + }, + "D10": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 47.38, + "z": 1.5 + }, + "D11": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 47.38, + "z": 1.5 + }, + "D12": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 47.38, + "z": 1.5 + }, + "D2": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 47.38, + "z": 1.5 + }, + "D3": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 47.38, + "z": 1.5 + }, + "D4": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 47.38, + "z": 1.5 + }, + "D5": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 47.38, + "z": 1.5 + }, + "D6": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 47.38, + "z": 1.5 + }, + "D7": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 47.38, + "z": 1.5 + }, + "D8": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 47.38, + "z": 1.5 + }, + "D9": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 47.38, + "z": 1.5 + }, + "E1": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 38.38, + "z": 1.5 + }, + "E10": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 38.38, + "z": 1.5 + }, + "E11": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 38.38, + "z": 1.5 + }, + "E12": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 38.38, + "z": 1.5 + }, + "E2": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 38.38, + "z": 1.5 + }, + "E3": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 38.38, + "z": 1.5 + }, + "E4": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 38.38, + "z": 1.5 + }, + "E5": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 38.38, + "z": 1.5 + }, + "E6": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 38.38, + "z": 1.5 + }, + "E7": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 38.38, + "z": 1.5 + }, + "E8": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 38.38, + "z": 1.5 + }, + "E9": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 38.38, + "z": 1.5 + }, + "F1": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 29.38, + "z": 1.5 + }, + "F10": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 29.38, + "z": 1.5 + }, + "F11": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 29.38, + "z": 1.5 + }, + "F12": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 29.38, + "z": 1.5 + }, + "F2": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 29.38, + "z": 1.5 + }, + "F3": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 29.38, + "z": 1.5 + }, + "F4": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 29.38, + "z": 1.5 + }, + "F5": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 29.38, + "z": 1.5 + }, + "F6": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 29.38, + "z": 1.5 + }, + "F7": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 29.38, + "z": 1.5 + }, + "F8": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 29.38, + "z": 1.5 + }, + "F9": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 29.38, + "z": 1.5 + }, + "G1": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 20.38, + "z": 1.5 + }, + "G10": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 20.38, + "z": 1.5 + }, + "G11": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 20.38, + "z": 1.5 + }, + "G12": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 20.38, + "z": 1.5 + }, + "G2": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 20.38, + "z": 1.5 + }, + "G3": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 20.38, + "z": 1.5 + }, + "G4": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 20.38, + "z": 1.5 + }, + "G5": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 20.38, + "z": 1.5 + }, + "G6": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 20.38, + "z": 1.5 + }, + "G7": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 20.38, + "z": 1.5 + }, + "G8": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 20.38, + "z": 1.5 + }, + "G9": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 20.38, + "z": 1.5 + }, + "H1": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 11.38, + "z": 1.5 + }, + "H10": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 11.38, + "z": 1.5 + }, + "H11": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 11.38, + "z": 1.5 + }, + "H12": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 11.38, + "z": 1.5 + }, + "H2": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 11.38, + "z": 1.5 + }, + "H3": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 11.38, + "z": 1.5 + }, + "H4": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 11.38, + "z": 1.5 + }, + "H5": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 11.38, + "z": 1.5 + }, + "H6": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 11.38, + "z": 1.5 + }, + "H7": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 11.38, + "z": 1.5 + }, + "H8": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 11.38, + "z": 1.5 + }, + "H9": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 11.38, + "z": 1.5 + } + } + }, + "labwareId": "UUID" + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "loadLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "17ae05bacb1938a44ffcedba774adf48", + "notes": [], + "params": { + "loadName": "opentrons_flex_96_tiprack_1000ul", + "location": { + "slotName": "C3" + }, + "namespace": "opentrons", + "version": 1 + }, + "result": { + "definition": { + "allowedRoles": [], + "brand": { + "brand": "Opentrons", + "brandId": [] + }, + "cornerOffsetFromSlot": { + "x": 0, + "y": 0, + "z": 0 + }, + "dimensions": { + "xDimension": 127.75, + "yDimension": 85.75, + "zDimension": 99 + }, + "gripForce": 16.0, + "gripHeightFromLabwareBottom": 23.9, + "gripperOffsets": {}, + "groups": [ + { + "metadata": {}, + "wells": [ + "A1", + "A10", + "A11", + "A12", + "A2", + "A3", + "A4", + "A5", + "A6", + "A7", + "A8", + "A9", + "B1", + "B10", + "B11", + "B12", + "B2", + "B3", + "B4", + "B5", + "B6", + "B7", + "B8", + "B9", + "C1", + "C10", + "C11", + "C12", + "C2", + "C3", + "C4", + "C5", + "C6", + "C7", + "C8", + "C9", + "D1", + "D10", + "D11", + "D12", + "D2", + "D3", + "D4", + "D5", + "D6", + "D7", + "D8", + "D9", + "E1", + "E10", + "E11", + "E12", + "E2", + "E3", + "E4", + "E5", + "E6", + "E7", + "E8", + "E9", + "F1", + "F10", + "F11", + "F12", + "F2", + "F3", + "F4", + "F5", + "F6", + "F7", + "F8", + "F9", + "G1", + "G10", + "G11", + "G12", + "G2", + "G3", + "G4", + "G5", + "G6", + "G7", + "G8", + "G9", + "H1", + "H10", + "H11", + "H12", + "H2", + "H3", + "H4", + "H5", + "H6", + "H7", + "H8", + "H9" + ] + } + ], + "metadata": { + "displayCategory": "tipRack", + "displayName": "Opentrons Flex 96 Tip Rack 1000 µL", + "displayVolumeUnits": "µL", + "tags": [] + }, + "namespace": "opentrons", + "ordering": [ + [ + "A1", + "B1", + "C1", + "D1", + "E1", + "F1", + "G1", + "H1" + ], + [ + "A10", + "B10", + "C10", + "D10", + "E10", + "F10", + "G10", + "H10" + ], + [ + "A11", + "B11", + "C11", + "D11", + "E11", + "F11", + "G11", + "H11" + ], + [ + "A12", + "B12", + "C12", + "D12", + "E12", + "F12", + "G12", + "H12" + ], + [ + "A2", + "B2", + "C2", + "D2", + "E2", + "F2", + "G2", + "H2" + ], + [ + "A3", + "B3", + "C3", + "D3", + "E3", + "F3", + "G3", + "H3" + ], + [ + "A4", + "B4", + "C4", + "D4", + "E4", + "F4", + "G4", + "H4" + ], + [ + "A5", + "B5", + "C5", + "D5", + "E5", + "F5", + "G5", + "H5" + ], + [ + "A6", + "B6", + "C6", + "D6", + "E6", + "F6", + "G6", + "H6" + ], + [ + "A7", + "B7", + "C7", + "D7", + "E7", + "F7", + "G7", + "H7" + ], + [ + "A8", + "B8", + "C8", + "D8", + "E8", + "F8", + "G8", + "H8" + ], + [ + "A9", + "B9", + "C9", + "D9", + "E9", + "F9", + "G9", + "H9" + ] + ], + "parameters": { + "format": "96Standard", + "isMagneticModuleCompatible": false, + "isTiprack": true, + "loadName": "opentrons_flex_96_tiprack_1000ul", + "quirks": [], + "tipLength": 95.6, + "tipOverlap": 10.5 + }, + "schemaVersion": 2, + "stackingOffsetWithLabware": { + "opentrons_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 121 + } + }, + "stackingOffsetWithModule": {}, + "version": 1, + "wells": { + "A1": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 74.38, + "z": 1.5 + }, + "A10": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 74.38, + "z": 1.5 + }, + "A11": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 74.38, + "z": 1.5 + }, + "A12": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 74.38, + "z": 1.5 + }, + "A2": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 74.38, + "z": 1.5 + }, + "A3": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 74.38, + "z": 1.5 + }, + "A4": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 74.38, + "z": 1.5 + }, + "A5": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 74.38, + "z": 1.5 + }, + "A6": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 74.38, + "z": 1.5 + }, + "A7": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 74.38, + "z": 1.5 + }, + "A8": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 74.38, + "z": 1.5 + }, + "A9": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 74.38, + "z": 1.5 + }, + "B1": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 65.38, + "z": 1.5 + }, + "B10": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 65.38, + "z": 1.5 + }, + "B11": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 65.38, + "z": 1.5 + }, + "B12": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 65.38, + "z": 1.5 + }, + "B2": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 65.38, + "z": 1.5 + }, + "B3": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 65.38, + "z": 1.5 + }, + "B4": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 65.38, + "z": 1.5 + }, + "B5": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 65.38, + "z": 1.5 + }, + "B6": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 65.38, + "z": 1.5 + }, + "B7": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 65.38, + "z": 1.5 + }, + "B8": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 65.38, + "z": 1.5 + }, + "B9": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 65.38, + "z": 1.5 + }, + "C1": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 56.38, + "z": 1.5 + }, + "C10": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 56.38, + "z": 1.5 + }, + "C11": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 56.38, + "z": 1.5 + }, + "C12": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 56.38, + "z": 1.5 + }, + "C2": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 56.38, + "z": 1.5 + }, + "C3": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 56.38, + "z": 1.5 + }, + "C4": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 56.38, + "z": 1.5 + }, + "C5": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 56.38, + "z": 1.5 + }, + "C6": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 56.38, + "z": 1.5 + }, + "C7": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 56.38, + "z": 1.5 + }, + "C8": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 56.38, + "z": 1.5 + }, + "C9": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 56.38, + "z": 1.5 + }, + "D1": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 47.38, + "z": 1.5 + }, + "D10": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 47.38, + "z": 1.5 + }, + "D11": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 47.38, + "z": 1.5 + }, + "D12": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 47.38, + "z": 1.5 + }, + "D2": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 47.38, + "z": 1.5 + }, + "D3": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 47.38, + "z": 1.5 + }, + "D4": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 47.38, + "z": 1.5 + }, + "D5": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 47.38, + "z": 1.5 + }, + "D6": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 47.38, + "z": 1.5 + }, + "D7": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 47.38, + "z": 1.5 + }, + "D8": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 47.38, + "z": 1.5 + }, + "D9": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 47.38, + "z": 1.5 + }, + "E1": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 38.38, + "z": 1.5 + }, + "E10": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 38.38, + "z": 1.5 + }, + "E11": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 38.38, + "z": 1.5 + }, + "E12": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 38.38, + "z": 1.5 + }, + "E2": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 38.38, + "z": 1.5 + }, + "E3": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 38.38, + "z": 1.5 + }, + "E4": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 38.38, + "z": 1.5 + }, + "E5": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 38.38, + "z": 1.5 + }, + "E6": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 38.38, + "z": 1.5 + }, + "E7": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 38.38, + "z": 1.5 + }, + "E8": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 38.38, + "z": 1.5 + }, + "E9": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 38.38, + "z": 1.5 + }, + "F1": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 29.38, + "z": 1.5 + }, + "F10": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 29.38, + "z": 1.5 + }, + "F11": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 29.38, + "z": 1.5 + }, + "F12": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 29.38, + "z": 1.5 + }, + "F2": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 29.38, + "z": 1.5 + }, + "F3": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 29.38, + "z": 1.5 + }, + "F4": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 29.38, + "z": 1.5 + }, + "F5": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 29.38, + "z": 1.5 + }, + "F6": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 29.38, + "z": 1.5 + }, + "F7": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 29.38, + "z": 1.5 + }, + "F8": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 29.38, + "z": 1.5 + }, + "F9": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 29.38, + "z": 1.5 + }, + "G1": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 20.38, + "z": 1.5 + }, + "G10": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 20.38, + "z": 1.5 + }, + "G11": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 20.38, + "z": 1.5 + }, + "G12": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 20.38, + "z": 1.5 + }, + "G2": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 20.38, + "z": 1.5 + }, + "G3": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 20.38, + "z": 1.5 + }, + "G4": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 20.38, + "z": 1.5 + }, + "G5": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 20.38, + "z": 1.5 + }, + "G6": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 20.38, + "z": 1.5 + }, + "G7": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 20.38, + "z": 1.5 + }, + "G8": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 20.38, + "z": 1.5 + }, + "G9": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 20.38, + "z": 1.5 + }, + "H1": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 11.38, + "z": 1.5 + }, + "H10": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 11.38, + "z": 1.5 + }, + "H11": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 11.38, + "z": 1.5 + }, + "H12": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 11.38, + "z": 1.5 + }, + "H2": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 11.38, + "z": 1.5 + }, + "H3": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 11.38, + "z": 1.5 + }, + "H4": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 11.38, + "z": 1.5 + }, + "H5": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 11.38, + "z": 1.5 + }, + "H6": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 11.38, + "z": 1.5 + }, + "H7": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 11.38, + "z": 1.5 + }, + "H8": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 11.38, + "z": 1.5 + }, + "H9": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 11.38, + "z": 1.5 + } + } + }, + "labwareId": "UUID" + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "loadLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "26fd355fdb8b0c88fb550b0f1f1efd5d", + "notes": [], + "params": { + "loadName": "opentrons_flex_96_tiprack_1000ul", + "location": { + "addressableAreaName": "C4" + }, + "namespace": "opentrons", + "version": 1 + }, + "result": { + "definition": { + "allowedRoles": [], + "brand": { + "brand": "Opentrons", + "brandId": [] + }, + "cornerOffsetFromSlot": { + "x": 0, + "y": 0, + "z": 0 + }, + "dimensions": { + "xDimension": 127.75, + "yDimension": 85.75, + "zDimension": 99 + }, + "gripForce": 16.0, + "gripHeightFromLabwareBottom": 23.9, + "gripperOffsets": {}, + "groups": [ + { + "metadata": {}, + "wells": [ + "A1", + "A10", + "A11", + "A12", + "A2", + "A3", + "A4", + "A5", + "A6", + "A7", + "A8", + "A9", + "B1", + "B10", + "B11", + "B12", + "B2", + "B3", + "B4", + "B5", + "B6", + "B7", + "B8", + "B9", + "C1", + "C10", + "C11", + "C12", + "C2", + "C3", + "C4", + "C5", + "C6", + "C7", + "C8", + "C9", + "D1", + "D10", + "D11", + "D12", + "D2", + "D3", + "D4", + "D5", + "D6", + "D7", + "D8", + "D9", + "E1", + "E10", + "E11", + "E12", + "E2", + "E3", + "E4", + "E5", + "E6", + "E7", + "E8", + "E9", + "F1", + "F10", + "F11", + "F12", + "F2", + "F3", + "F4", + "F5", + "F6", + "F7", + "F8", + "F9", + "G1", + "G10", + "G11", + "G12", + "G2", + "G3", + "G4", + "G5", + "G6", + "G7", + "G8", + "G9", + "H1", + "H10", + "H11", + "H12", + "H2", + "H3", + "H4", + "H5", + "H6", + "H7", + "H8", + "H9" + ] + } + ], + "metadata": { + "displayCategory": "tipRack", + "displayName": "Opentrons Flex 96 Tip Rack 1000 µL", + "displayVolumeUnits": "µL", + "tags": [] + }, + "namespace": "opentrons", + "ordering": [ + [ + "A1", + "B1", + "C1", + "D1", + "E1", + "F1", + "G1", + "H1" + ], + [ + "A10", + "B10", + "C10", + "D10", + "E10", + "F10", + "G10", + "H10" + ], + [ + "A11", + "B11", + "C11", + "D11", + "E11", + "F11", + "G11", + "H11" + ], + [ + "A12", + "B12", + "C12", + "D12", + "E12", + "F12", + "G12", + "H12" + ], + [ + "A2", + "B2", + "C2", + "D2", + "E2", + "F2", + "G2", + "H2" + ], + [ + "A3", + "B3", + "C3", + "D3", + "E3", + "F3", + "G3", + "H3" + ], + [ + "A4", + "B4", + "C4", + "D4", + "E4", + "F4", + "G4", + "H4" + ], + [ + "A5", + "B5", + "C5", + "D5", + "E5", + "F5", + "G5", + "H5" + ], + [ + "A6", + "B6", + "C6", + "D6", + "E6", + "F6", + "G6", + "H6" + ], + [ + "A7", + "B7", + "C7", + "D7", + "E7", + "F7", + "G7", + "H7" + ], + [ + "A8", + "B8", + "C8", + "D8", + "E8", + "F8", + "G8", + "H8" + ], + [ + "A9", + "B9", + "C9", + "D9", + "E9", + "F9", + "G9", + "H9" + ] + ], + "parameters": { + "format": "96Standard", + "isMagneticModuleCompatible": false, + "isTiprack": true, + "loadName": "opentrons_flex_96_tiprack_1000ul", + "quirks": [], + "tipLength": 95.6, + "tipOverlap": 10.5 + }, + "schemaVersion": 2, + "stackingOffsetWithLabware": { + "opentrons_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 121 + } + }, + "stackingOffsetWithModule": {}, + "version": 1, + "wells": { + "A1": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 74.38, + "z": 1.5 + }, + "A10": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 74.38, + "z": 1.5 + }, + "A11": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 74.38, + "z": 1.5 + }, + "A12": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 74.38, + "z": 1.5 + }, + "A2": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 74.38, + "z": 1.5 + }, + "A3": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 74.38, + "z": 1.5 + }, + "A4": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 74.38, + "z": 1.5 + }, + "A5": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 74.38, + "z": 1.5 + }, + "A6": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 74.38, + "z": 1.5 + }, + "A7": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 74.38, + "z": 1.5 + }, + "A8": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 74.38, + "z": 1.5 + }, + "A9": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 74.38, + "z": 1.5 + }, + "B1": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 65.38, + "z": 1.5 + }, + "B10": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 65.38, + "z": 1.5 + }, + "B11": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 65.38, + "z": 1.5 + }, + "B12": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 65.38, + "z": 1.5 + }, + "B2": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 65.38, + "z": 1.5 + }, + "B3": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 65.38, + "z": 1.5 + }, + "B4": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 65.38, + "z": 1.5 + }, + "B5": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 65.38, + "z": 1.5 + }, + "B6": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 65.38, + "z": 1.5 + }, + "B7": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 65.38, + "z": 1.5 + }, + "B8": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 65.38, + "z": 1.5 + }, + "B9": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 65.38, + "z": 1.5 + }, + "C1": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 56.38, + "z": 1.5 + }, + "C10": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 56.38, + "z": 1.5 + }, + "C11": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 56.38, + "z": 1.5 + }, + "C12": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 56.38, + "z": 1.5 + }, + "C2": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 56.38, + "z": 1.5 + }, + "C3": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 56.38, + "z": 1.5 + }, + "C4": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 56.38, + "z": 1.5 + }, + "C5": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 56.38, + "z": 1.5 + }, + "C6": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 56.38, + "z": 1.5 + }, + "C7": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 56.38, + "z": 1.5 + }, + "C8": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 56.38, + "z": 1.5 + }, + "C9": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 56.38, + "z": 1.5 + }, + "D1": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 47.38, + "z": 1.5 + }, + "D10": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 47.38, + "z": 1.5 + }, + "D11": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 47.38, + "z": 1.5 + }, + "D12": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 47.38, + "z": 1.5 + }, + "D2": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 47.38, + "z": 1.5 + }, + "D3": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 47.38, + "z": 1.5 + }, + "D4": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 47.38, + "z": 1.5 + }, + "D5": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 47.38, + "z": 1.5 + }, + "D6": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 47.38, + "z": 1.5 + }, + "D7": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 47.38, + "z": 1.5 + }, + "D8": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 47.38, + "z": 1.5 + }, + "D9": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 47.38, + "z": 1.5 + }, + "E1": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 38.38, + "z": 1.5 + }, + "E10": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 38.38, + "z": 1.5 + }, + "E11": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 38.38, + "z": 1.5 + }, + "E12": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 38.38, + "z": 1.5 + }, + "E2": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 38.38, + "z": 1.5 + }, + "E3": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 38.38, + "z": 1.5 + }, + "E4": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 38.38, + "z": 1.5 + }, + "E5": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 38.38, + "z": 1.5 + }, + "E6": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 38.38, + "z": 1.5 + }, + "E7": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 38.38, + "z": 1.5 + }, + "E8": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 38.38, + "z": 1.5 + }, + "E9": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 38.38, + "z": 1.5 + }, + "F1": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 29.38, + "z": 1.5 + }, + "F10": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 29.38, + "z": 1.5 + }, + "F11": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 29.38, + "z": 1.5 + }, + "F12": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 29.38, + "z": 1.5 + }, + "F2": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 29.38, + "z": 1.5 + }, + "F3": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 29.38, + "z": 1.5 + }, + "F4": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 29.38, + "z": 1.5 + }, + "F5": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 29.38, + "z": 1.5 + }, + "F6": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 29.38, + "z": 1.5 + }, + "F7": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 29.38, + "z": 1.5 + }, + "F8": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 29.38, + "z": 1.5 + }, + "F9": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 29.38, + "z": 1.5 + }, + "G1": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 20.38, + "z": 1.5 + }, + "G10": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 20.38, + "z": 1.5 + }, + "G11": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 20.38, + "z": 1.5 + }, + "G12": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 20.38, + "z": 1.5 + }, + "G2": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 20.38, + "z": 1.5 + }, + "G3": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 20.38, + "z": 1.5 + }, + "G4": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 20.38, + "z": 1.5 + }, + "G5": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 20.38, + "z": 1.5 + }, + "G6": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 20.38, + "z": 1.5 + }, + "G7": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 20.38, + "z": 1.5 + }, + "G8": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 20.38, + "z": 1.5 + }, + "G9": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 20.38, + "z": 1.5 + }, + "H1": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 11.38, + "z": 1.5 + }, + "H10": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 11.38, + "z": 1.5 + }, + "H11": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 11.38, + "z": 1.5 + }, + "H12": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 11.38, + "z": 1.5 + }, + "H2": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 11.38, + "z": 1.5 + }, + "H3": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 11.38, + "z": 1.5 + }, + "H4": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 11.38, + "z": 1.5 + }, + "H5": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 11.38, + "z": 1.5 + }, + "H6": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 11.38, + "z": 1.5 + }, + "H7": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 11.38, + "z": 1.5 + }, + "H8": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 11.38, + "z": 1.5 + }, + "H9": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 11.38, + "z": 1.5 + } + } + }, + "labwareId": "UUID" + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "loadLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "8536492bbcebe772a2f733df19c99c4f", + "notes": [], + "params": { + "loadName": "opentrons_flex_96_tiprack_1000ul", + "location": "offDeck", + "namespace": "opentrons", + "version": 1 + }, + "result": { + "definition": { + "allowedRoles": [], + "brand": { + "brand": "Opentrons", + "brandId": [] + }, + "cornerOffsetFromSlot": { + "x": 0, + "y": 0, + "z": 0 + }, + "dimensions": { + "xDimension": 127.75, + "yDimension": 85.75, + "zDimension": 99 + }, + "gripForce": 16.0, + "gripHeightFromLabwareBottom": 23.9, + "gripperOffsets": {}, + "groups": [ + { + "metadata": {}, + "wells": [ + "A1", + "A10", + "A11", + "A12", + "A2", + "A3", + "A4", + "A5", + "A6", + "A7", + "A8", + "A9", + "B1", + "B10", + "B11", + "B12", + "B2", + "B3", + "B4", + "B5", + "B6", + "B7", + "B8", + "B9", + "C1", + "C10", + "C11", + "C12", + "C2", + "C3", + "C4", + "C5", + "C6", + "C7", + "C8", + "C9", + "D1", + "D10", + "D11", + "D12", + "D2", + "D3", + "D4", + "D5", + "D6", + "D7", + "D8", + "D9", + "E1", + "E10", + "E11", + "E12", + "E2", + "E3", + "E4", + "E5", + "E6", + "E7", + "E8", + "E9", + "F1", + "F10", + "F11", + "F12", + "F2", + "F3", + "F4", + "F5", + "F6", + "F7", + "F8", + "F9", + "G1", + "G10", + "G11", + "G12", + "G2", + "G3", + "G4", + "G5", + "G6", + "G7", + "G8", + "G9", + "H1", + "H10", + "H11", + "H12", + "H2", + "H3", + "H4", + "H5", + "H6", + "H7", + "H8", + "H9" + ] + } + ], + "metadata": { + "displayCategory": "tipRack", + "displayName": "Opentrons Flex 96 Tip Rack 1000 µL", + "displayVolumeUnits": "µL", + "tags": [] + }, + "namespace": "opentrons", + "ordering": [ + [ + "A1", + "B1", + "C1", + "D1", + "E1", + "F1", + "G1", + "H1" + ], + [ + "A10", + "B10", + "C10", + "D10", + "E10", + "F10", + "G10", + "H10" + ], + [ + "A11", + "B11", + "C11", + "D11", + "E11", + "F11", + "G11", + "H11" + ], + [ + "A12", + "B12", + "C12", + "D12", + "E12", + "F12", + "G12", + "H12" + ], + [ + "A2", + "B2", + "C2", + "D2", + "E2", + "F2", + "G2", + "H2" + ], + [ + "A3", + "B3", + "C3", + "D3", + "E3", + "F3", + "G3", + "H3" + ], + [ + "A4", + "B4", + "C4", + "D4", + "E4", + "F4", + "G4", + "H4" + ], + [ + "A5", + "B5", + "C5", + "D5", + "E5", + "F5", + "G5", + "H5" + ], + [ + "A6", + "B6", + "C6", + "D6", + "E6", + "F6", + "G6", + "H6" + ], + [ + "A7", + "B7", + "C7", + "D7", + "E7", + "F7", + "G7", + "H7" + ], + [ + "A8", + "B8", + "C8", + "D8", + "E8", + "F8", + "G8", + "H8" + ], + [ + "A9", + "B9", + "C9", + "D9", + "E9", + "F9", + "G9", + "H9" + ] + ], + "parameters": { + "format": "96Standard", + "isMagneticModuleCompatible": false, + "isTiprack": true, + "loadName": "opentrons_flex_96_tiprack_1000ul", + "quirks": [], + "tipLength": 95.6, + "tipOverlap": 10.5 + }, + "schemaVersion": 2, + "stackingOffsetWithLabware": { + "opentrons_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 121 + } + }, + "stackingOffsetWithModule": {}, + "version": 1, + "wells": { + "A1": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 74.38, + "z": 1.5 + }, + "A10": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 74.38, + "z": 1.5 + }, + "A11": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 74.38, + "z": 1.5 + }, + "A12": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 74.38, + "z": 1.5 + }, + "A2": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 74.38, + "z": 1.5 + }, + "A3": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 74.38, + "z": 1.5 + }, + "A4": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 74.38, + "z": 1.5 + }, + "A5": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 74.38, + "z": 1.5 + }, + "A6": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 74.38, + "z": 1.5 + }, + "A7": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 74.38, + "z": 1.5 + }, + "A8": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 74.38, + "z": 1.5 + }, + "A9": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 74.38, + "z": 1.5 + }, + "B1": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 65.38, + "z": 1.5 + }, + "B10": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 65.38, + "z": 1.5 + }, + "B11": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 65.38, + "z": 1.5 + }, + "B12": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 65.38, + "z": 1.5 + }, + "B2": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 65.38, + "z": 1.5 + }, + "B3": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 65.38, + "z": 1.5 + }, + "B4": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 65.38, + "z": 1.5 + }, + "B5": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 65.38, + "z": 1.5 + }, + "B6": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 65.38, + "z": 1.5 + }, + "B7": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 65.38, + "z": 1.5 + }, + "B8": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 65.38, + "z": 1.5 + }, + "B9": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 65.38, + "z": 1.5 + }, + "C1": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 56.38, + "z": 1.5 + }, + "C10": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 56.38, + "z": 1.5 + }, + "C11": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 56.38, + "z": 1.5 + }, + "C12": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 56.38, + "z": 1.5 + }, + "C2": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 56.38, + "z": 1.5 + }, + "C3": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 56.38, + "z": 1.5 + }, + "C4": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 56.38, + "z": 1.5 + }, + "C5": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 56.38, + "z": 1.5 + }, + "C6": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 56.38, + "z": 1.5 + }, + "C7": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 56.38, + "z": 1.5 + }, + "C8": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 56.38, + "z": 1.5 + }, + "C9": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 56.38, + "z": 1.5 + }, + "D1": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 47.38, + "z": 1.5 + }, + "D10": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 47.38, + "z": 1.5 + }, + "D11": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 47.38, + "z": 1.5 + }, + "D12": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 47.38, + "z": 1.5 + }, + "D2": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 47.38, + "z": 1.5 + }, + "D3": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 47.38, + "z": 1.5 + }, + "D4": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 47.38, + "z": 1.5 + }, + "D5": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 47.38, + "z": 1.5 + }, + "D6": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 47.38, + "z": 1.5 + }, + "D7": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 47.38, + "z": 1.5 + }, + "D8": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 47.38, + "z": 1.5 + }, + "D9": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 47.38, + "z": 1.5 + }, + "E1": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 38.38, + "z": 1.5 + }, + "E10": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 38.38, + "z": 1.5 + }, + "E11": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 38.38, + "z": 1.5 + }, + "E12": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 38.38, + "z": 1.5 + }, + "E2": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 38.38, + "z": 1.5 + }, + "E3": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 38.38, + "z": 1.5 + }, + "E4": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 38.38, + "z": 1.5 + }, + "E5": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 38.38, + "z": 1.5 + }, + "E6": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 38.38, + "z": 1.5 + }, + "E7": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 38.38, + "z": 1.5 + }, + "E8": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 38.38, + "z": 1.5 + }, + "E9": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 38.38, + "z": 1.5 + }, + "F1": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 29.38, + "z": 1.5 + }, + "F10": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 29.38, + "z": 1.5 + }, + "F11": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 29.38, + "z": 1.5 + }, + "F12": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 29.38, + "z": 1.5 + }, + "F2": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 29.38, + "z": 1.5 + }, + "F3": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 29.38, + "z": 1.5 + }, + "F4": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 29.38, + "z": 1.5 + }, + "F5": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 29.38, + "z": 1.5 + }, + "F6": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 29.38, + "z": 1.5 + }, + "F7": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 29.38, + "z": 1.5 + }, + "F8": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 29.38, + "z": 1.5 + }, + "F9": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 29.38, + "z": 1.5 + }, + "G1": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 20.38, + "z": 1.5 + }, + "G10": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 20.38, + "z": 1.5 + }, + "G11": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 20.38, + "z": 1.5 + }, + "G12": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 20.38, + "z": 1.5 + }, + "G2": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 20.38, + "z": 1.5 + }, + "G3": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 20.38, + "z": 1.5 + }, + "G4": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 20.38, + "z": 1.5 + }, + "G5": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 20.38, + "z": 1.5 + }, + "G6": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 20.38, + "z": 1.5 + }, + "G7": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 20.38, + "z": 1.5 + }, + "G8": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 20.38, + "z": 1.5 + }, + "G9": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 20.38, + "z": 1.5 + }, + "H1": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 11.38, + "z": 1.5 + }, + "H10": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 11.38, + "z": 1.5 + }, + "H11": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 11.38, + "z": 1.5 + }, + "H12": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 11.38, + "z": 1.5 + }, + "H2": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 11.38, + "z": 1.5 + }, + "H3": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 11.38, + "z": 1.5 + }, + "H4": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 11.38, + "z": 1.5 + }, + "H5": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 11.38, + "z": 1.5 + }, + "H6": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 11.38, + "z": 1.5 + }, + "H7": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 11.38, + "z": 1.5 + }, + "H8": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 11.38, + "z": 1.5 + }, + "H9": { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 11.38, + "z": 1.5 + } + } + }, + "labwareId": "UUID" + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "loadPipette", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "1da6a76a5f9ccc6dc5311b4dda81e70e", + "notes": [], + "params": { + "liquidPresenceDetection": true, + "mount": "left", + "pipetteName": "p1000_96", + "tipOverlapNotAfterVersion": "v3" + }, + "result": { + "pipetteId": "UUID" + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "loadLiquid", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "898a866117a32fd68820a6526bef6db3", + "notes": [], + "params": { + "labwareId": "UUID", + "liquidId": "UUID", + "volumeByWell": { + "A1": 29000.0 + } + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "e225750b329b6840e7e27634e9e12b6f", + "notes": [], + "params": { + "message": "Item opentrons_96_wellplate_200ul_pcr_full_skirt is at C2" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "moveLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "d394c9aab9575b56edd3ad97b0355259", + "notes": [], + "params": { + "labwareId": "UUID", + "newLocation": { + "moduleId": "UUID" + }, + "strategy": "usingGripper" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "1bb0adb1034d8481ac12eaa7f7c1c3ef", + "notes": [], + "params": { + "message": "Item opentrons_96_wellplate_200ul_pcr_full_skirt is at ThermocyclerContext at Thermocycler Module GEN2 on B1 lw Opentrons Tough 96 Well Plate 200 µL PCR Full Skirt" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "moveLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "017ca5d99c90c0bba8904243fcd89832", + "notes": [], + "params": { + "labwareId": "UUID", + "newLocation": { + "slotName": "C2" + }, + "strategy": "usingGripper" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "8011dfe9e544689ec795e643c88ac270", + "notes": [], + "params": { + "message": "Item opentrons_96_wellplate_200ul_pcr_full_skirt is at C2" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "66b606966287f93e943cbe1c210953de", + "notes": [], + "params": { + "message": "Item nest_1_reservoir_290ml is at D2" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "moveLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "c63414793ccc12f468292d27a7c23bd0", + "notes": [], + "params": { + "labwareId": "UUID", + "newLocation": { + "addressableAreaName": "D4" + }, + "strategy": "manualMoveWithPause" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "ddcaec056e1697e98605f81b27c3aab1", + "notes": [], + "params": { + "message": "Item nest_1_reservoir_290ml is at D4" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "moveLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "7a3df36a08d870099052afb8a0cda156", + "notes": [], + "params": { + "labwareId": "UUID", + "newLocation": { + "slotName": "D2" + }, + "strategy": "usingGripper" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "3f060abc43588bf1cb31c84334652741", + "notes": [], + "params": { + "message": "Item nest_1_reservoir_290ml is at D2" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "configureNozzleLayout", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "54f7126428b3d9ccbdfecf81650de609", + "notes": [], + "params": { + "configurationParams": { + "primaryNozzle": "A12", + "style": "COLUMN" + }, + "pipetteId": "UUID" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "pickUpTip", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "870404c9b72d6bd37634d8e6beca84c6", + "notes": [], + "params": { + "labwareId": "UUID", + "pipetteId": "UUID", + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "origin": "top" + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 342.38, + "y": 181.38, + "z": 99.0 + }, + "tipDiameter": 5.47, + "tipLength": 85.38999999999999, + "tipVolume": 1000.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "32e38e175b6506181d178153d765b0c7", + "notes": [], + "params": { + "message": "Tip rack in C3" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "f2ed2d040deab45db33b562c016689b3", + "notes": [], + "params": { + "message": "A: A1 ❌ A2 🟢 A3 🟢 A4 🟢 A5 🟢 A6 🟢 A7 🟢 A8 🟢 A9 🟢 A10 🟢 A11 🟢 A12 🟢 " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "8f7ef35977c269c26521ac70ba964663", + "notes": [], + "params": { + "message": "B: B1 ❌ B2 🟢 B3 🟢 B4 🟢 B5 🟢 B6 🟢 B7 🟢 B8 🟢 B9 🟢 B10 🟢 B11 🟢 B12 🟢 " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "bf11e9838b6269c7fd170ae415a52ccf", + "notes": [], + "params": { + "message": "C: C1 ❌ C2 🟢 C3 🟢 C4 🟢 C5 🟢 C6 🟢 C7 🟢 C8 🟢 C9 🟢 C10 🟢 C11 🟢 C12 🟢 " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "95db1fadf1b23523b5453e177b9c50da", + "notes": [], + "params": { + "message": "D: D1 ❌ D2 🟢 D3 🟢 D4 🟢 D5 🟢 D6 🟢 D7 🟢 D8 🟢 D9 🟢 D10 🟢 D11 🟢 D12 🟢 " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "f9800b33ba24bddcacb0db7eca628061", + "notes": [], + "params": { + "message": "E: E1 ❌ E2 🟢 E3 🟢 E4 🟢 E5 🟢 E6 🟢 E7 🟢 E8 🟢 E9 🟢 E10 🟢 E11 🟢 E12 🟢 " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "107ef8bbe6742f96c6de7294af9a164c", + "notes": [], + "params": { + "message": "F: F1 ❌ F2 🟢 F3 🟢 F4 🟢 F5 🟢 F6 🟢 F7 🟢 F8 🟢 F9 🟢 F10 🟢 F11 🟢 F12 🟢 " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "ad4f7d4dcb71d186df59ccf1c9f1ca10", + "notes": [], + "params": { + "message": "G: G1 ❌ G2 🟢 G3 🟢 G4 🟢 G5 🟢 G6 🟢 G7 🟢 G8 🟢 G9 🟢 G10 🟢 G11 🟢 G12 🟢 " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "91351b86cc3e4dc2177314888ecbc2be", + "notes": [], + "params": { + "message": "H: H1 ❌ H2 🟢 H3 🟢 H4 🟢 H5 🟢 H6 🟢 H7 🟢 H8 🟢 H9 🟢 H10 🟢 H11 🟢 H12 🟢 " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "liquidProbe", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "183da52c0f8f8b79d27c6b68d2b170e5", + "notes": [], + "params": { + "labwareId": "UUID", + "pipetteId": "UUID", + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": 2.0 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 46.4 + }, + "z_position": 39.55 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "aspirate", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "7b296211cf41fa707f71d42cea453414", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "volume": 5.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -38.55 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 5.85 + }, + "volume": 5.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "dispense", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "0b8dd26114eb32bc6eeae9ae5ade6ebc", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "volume": 5.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -13.95 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 178.38, + "y": 181.24, + "z": 2.05 + }, + "volume": 5.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "moveToAddressableArea", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "8fdbbc092fe6f9f712459d911a673c02", + "notes": [], + "params": { + "addressableAreaName": "96ChannelWasteChute", + "forceDirect": false, + "offset": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "pipetteId": "UUID", + "stayAtHighestPossibleZ": false + }, + "result": { + "position": { + "x": 391.945, + "y": 10.585, + "z": 114.5 + } + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "dropTipInPlace", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "1d391eb17896c2f0a7d8fc6b1b08abc7", + "notes": [], + "params": { + "pipetteId": "UUID" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "configureNozzleLayout", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "81780206640aa0fd5e89455de48819ca", + "notes": [], + "params": { + "configurationParams": { + "primaryNozzle": "H12", + "style": "SINGLE" + }, + "pipetteId": "UUID" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "pickUpTip", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "8c4ee9b87303fb4539f304fa6130a437", + "notes": [], + "params": { + "labwareId": "UUID", + "pipetteId": "UUID", + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "origin": "top" + }, + "wellName": "A2" + }, + "result": { + "position": { + "x": 351.38, + "y": 181.38, + "z": 99.0 + }, + "tipDiameter": 5.47, + "tipLength": 85.38999999999999, + "tipVolume": 1000.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "liquidProbe", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "4bbd30c3fb3bae996d2ad6a0f436b68c", + "notes": [], + "params": { + "labwareId": "UUID", + "pipetteId": "UUID", + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": 2.0 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 46.4 + }, + "z_position": 39.55 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "aspirate", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "a7e370d997ef0a06985f630aff0b0509", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "volume": 5.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -38.55 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 5.85 + }, + "volume": 5.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "dispense", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "271e94d4af04613ce7a83bb5a883de6d", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "volume": 5.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -38.55 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 5.85 + }, + "volume": 5.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "liquidProbe", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "37521a0b1c1a673a476797b337d89d16", + "notes": [], + "params": { + "labwareId": "UUID", + "pipetteId": "UUID", + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": 2.0 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 46.4 + }, + "z_position": 39.55 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "aspirate", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "b30428396a416e3d22093cf4c773b47c", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "volume": 500.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -38.55 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 5.85 + }, + "volume": 500.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "dispense", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "49d59ded6092111efa96d0567bad1a49", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "volume": 500.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -38.55 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 5.85 + }, + "volume": 500.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "moveToAddressableArea", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "e77f6719b8f3419aa0b9f02fc60b9aa9", + "notes": [], + "params": { + "addressableAreaName": "96ChannelWasteChute", + "forceDirect": false, + "offset": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "pipetteId": "UUID", + "stayAtHighestPossibleZ": false + }, + "result": { + "position": { + "x": 391.945, + "y": 10.585, + "z": 114.5 + } + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "dropTipInPlace", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "478e3582f4eb2ed128a5daca61a4e9b6", + "notes": [], + "params": { + "pipetteId": "UUID" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "d117b92df9213935f80289757890dfb1", + "notes": [], + "params": { + "message": "Tip rack in C3" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "a08648d6082ed9ac8f0bbd06ad286f1a", + "notes": [], + "params": { + "message": "A: A1 ❌ A2 ❌ A3 🟢 A4 🟢 A5 🟢 A6 🟢 A7 🟢 A8 🟢 A9 🟢 A10 🟢 A11 🟢 A12 🟢 " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "786e445d77fb813503843582c1e0e240", + "notes": [], + "params": { + "message": "B: B1 ❌ B2 🟢 B3 🟢 B4 🟢 B5 🟢 B6 🟢 B7 🟢 B8 🟢 B9 🟢 B10 🟢 B11 🟢 B12 🟢 " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "5925cf7a20814afaf40e53aa8ae06558", + "notes": [], + "params": { + "message": "C: C1 ❌ C2 🟢 C3 🟢 C4 🟢 C5 🟢 C6 🟢 C7 🟢 C8 🟢 C9 🟢 C10 🟢 C11 🟢 C12 🟢 " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "6db826519588f9431bb3af0e3fa706c9", + "notes": [], + "params": { + "message": "D: D1 ❌ D2 🟢 D3 🟢 D4 🟢 D5 🟢 D6 🟢 D7 🟢 D8 🟢 D9 🟢 D10 🟢 D11 🟢 D12 🟢 " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "8ebd61bc9e0a48c2ede74a548db4a60c", + "notes": [], + "params": { + "message": "E: E1 ❌ E2 🟢 E3 🟢 E4 🟢 E5 🟢 E6 🟢 E7 🟢 E8 🟢 E9 🟢 E10 🟢 E11 🟢 E12 🟢 " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "9f42eca386eaaf3630878c24096682fc", + "notes": [], + "params": { + "message": "F: F1 ❌ F2 🟢 F3 🟢 F4 🟢 F5 🟢 F6 🟢 F7 🟢 F8 🟢 F9 🟢 F10 🟢 F11 🟢 F12 🟢 " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "1b7a1f8eb4e410f40b730ada3973af21", + "notes": [], + "params": { + "message": "G: G1 ❌ G2 🟢 G3 🟢 G4 🟢 G5 🟢 G6 🟢 G7 🟢 G8 🟢 G9 🟢 G10 🟢 G11 🟢 G12 🟢 " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "b80f271858de256646cdf2682ac749bf", + "notes": [], + "params": { + "message": "H: H1 ❌ H2 🟢 H3 🟢 H4 🟢 H5 🟢 H6 🟢 H7 🟢 H8 🟢 H9 🟢 H10 🟢 H11 🟢 H12 🟢 " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "moveLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "58570b636ea0e4ab4e3dca83d9414cfc", + "notes": [], + "params": { + "labwareId": "UUID", + "newLocation": { + "addressableAreaName": "gripperWasteChute" + }, + "strategy": "usingGripper" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "moveLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "d0db82bcc9973012d30c92664d808e18", + "notes": [], + "params": { + "labwareId": "UUID", + "newLocation": { + "slotName": "C3" + }, + "strategy": "usingGripper" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "configureNozzleLayout", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "d42132b53600539d7ad1de002cb0e06e", + "notes": [], + "params": { + "configurationParams": { + "primaryNozzle": "H1", + "style": "ROW" + }, + "pipetteId": "UUID" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "pickUpTip", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "7666f3511c92bd4c79c2f4796e187c6a", + "notes": [], + "params": { + "labwareId": "UUID", + "pipetteId": "UUID", + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "origin": "top" + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 342.38, + "y": 181.38, + "z": 99.0 + }, + "tipDiameter": 5.47, + "tipLength": 85.38999999999999, + "tipVolume": 1000.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "liquidProbe", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "e3c9e792dd81698a173ca216c297bf1c", + "notes": [], + "params": { + "labwareId": "UUID", + "pipetteId": "UUID", + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": 2.0 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 46.4 + }, + "z_position": 39.55 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "aspirate", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "c760f293c7e422858709f934985e1a7d", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "volume": 500.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -38.55 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 5.85 + }, + "volume": 500.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "dispense", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "9ead8491882088b5d251c946e6338db4", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "pushOut": 0.0, + "volume": 500.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -38.55 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 5.85 + }, + "volume": 500.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "aspirate", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "ce9a3b4288bf193a6e190156ac284977", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "volume": 500.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -38.55 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 5.85 + }, + "volume": 500.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "dispense", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "d9cd2dbdfc0197f336b169f58404a0fa", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "pushOut": 0.0, + "volume": 500.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -38.55 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 5.85 + }, + "volume": 500.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "aspirate", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "10498510a8ab571cad1b17f8cd0d38a2", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "volume": 500.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -38.55 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 5.85 + }, + "volume": 500.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "dispense", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "289400847435f9ac40532b1f0d4ddb62", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "volume": 500.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -38.55 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 5.85 + }, + "volume": 500.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "moveToAddressableArea", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "0d7d8f0b4cadfbe34a2e63b472ea515a", + "notes": [], + "params": { + "addressableAreaName": "96ChannelWasteChute", + "forceDirect": false, + "offset": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "pipetteId": "UUID", + "stayAtHighestPossibleZ": false + }, + "result": { + "position": { + "x": 391.945, + "y": 10.585, + "z": 114.5 + } + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "dropTipInPlace", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "5b98c2c25afe6ed45a9e5f7d53d10913", + "notes": [], + "params": { + "pipetteId": "UUID" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "f6d9c7f90feafa27f614adc77e3e4a6c", + "notes": [], + "params": { + "message": "Tip rack in C3" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "bd26801f990ee766417912053b5d1d85", + "notes": [], + "params": { + "message": "A: A1 ❌ A2 ❌ A3 ❌ A4 ❌ A5 ❌ A6 ❌ A7 ❌ A8 ❌ A9 ❌ A10 ❌ A11 ❌ A12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "6ce49ea6e7d7158920fe3037dd769a82", + "notes": [], + "params": { + "message": "B: B1 🟢 B2 🟢 B3 🟢 B4 🟢 B5 🟢 B6 🟢 B7 🟢 B8 🟢 B9 🟢 B10 🟢 B11 🟢 B12 🟢 " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "1ea2709eca69d325bac93d5c12b61102", + "notes": [], + "params": { + "message": "C: C1 🟢 C2 🟢 C3 🟢 C4 🟢 C5 🟢 C6 🟢 C7 🟢 C8 🟢 C9 🟢 C10 🟢 C11 🟢 C12 🟢 " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "e550f01cf1e380d18ddbcd7856a759a6", + "notes": [], + "params": { + "message": "D: D1 🟢 D2 🟢 D3 🟢 D4 🟢 D5 🟢 D6 🟢 D7 🟢 D8 🟢 D9 🟢 D10 🟢 D11 🟢 D12 🟢 " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "ad2af3e14a3d8ffb7814798537726073", + "notes": [], + "params": { + "message": "E: E1 🟢 E2 🟢 E3 🟢 E4 🟢 E5 🟢 E6 🟢 E7 🟢 E8 🟢 E9 🟢 E10 🟢 E11 🟢 E12 🟢 " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "32e88a4d628686db346517f72eacb3e9", + "notes": [], + "params": { + "message": "F: F1 🟢 F2 🟢 F3 🟢 F4 🟢 F5 🟢 F6 🟢 F7 🟢 F8 🟢 F9 🟢 F10 🟢 F11 🟢 F12 🟢 " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "71ae76605b9b3f27159f619b4fd24d77", + "notes": [], + "params": { + "message": "G: G1 🟢 G2 🟢 G3 🟢 G4 🟢 G5 🟢 G6 🟢 G7 🟢 G8 🟢 G9 🟢 G10 🟢 G11 🟢 G12 🟢 " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "a829ef01b67f8a6a5657384b811e8670", + "notes": [], + "params": { + "message": "H: H1 🟢 H2 🟢 H3 🟢 H4 🟢 H5 🟢 H6 🟢 H7 🟢 H8 🟢 H9 🟢 H10 🟢 H11 🟢 H12 🟢 " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "configureNozzleLayout", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "5365e04fad40b79ec18d0f0ec67be6b4", + "notes": [], + "params": { + "configurationParams": { + "style": "ALL" + }, + "pipetteId": "UUID" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "pickUpTip", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "ff11e465f62590cae83e688b10e2223f", + "notes": [], + "params": { + "labwareId": "UUID", + "pipetteId": "UUID", + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "origin": "top" + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 178.38, + "y": 395.38, + "z": 110.0 + }, + "tipDiameter": 5.47, + "tipLength": 85.38999999999999, + "tipVolume": 1000.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "9ad8654c7993d6585b0cbc6476129ff5", + "notes": [], + "params": { + "message": "Tip rack in Opentrons Flex 96 Tip Rack Adapter" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "73032c12c503d675d7394d98ebcaed59", + "notes": [], + "params": { + "message": "A: A1 ❌ A2 ❌ A3 ❌ A4 ❌ A5 ❌ A6 ❌ A7 ❌ A8 ❌ A9 ❌ A10 ❌ A11 ❌ A12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "8ae1d2605e1a91cc1c318849bfdada67", + "notes": [], + "params": { + "message": "B: B1 ❌ B2 ❌ B3 ❌ B4 ❌ B5 ❌ B6 ❌ B7 ❌ B8 ❌ B9 ❌ B10 ❌ B11 ❌ B12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "bae058c3acd2294054b74da2c83df5ba", + "notes": [], + "params": { + "message": "C: C1 ❌ C2 ❌ C3 ❌ C4 ❌ C5 ❌ C6 ❌ C7 ❌ C8 ❌ C9 ❌ C10 ❌ C11 ❌ C12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "ef186548c415cad51bd2c1f5a5ca6709", + "notes": [], + "params": { + "message": "D: D1 ❌ D2 ❌ D3 ❌ D4 ❌ D5 ❌ D6 ❌ D7 ❌ D8 ❌ D9 ❌ D10 ❌ D11 ❌ D12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "8654bf1423f4bc950cc979848c1922d5", + "notes": [], + "params": { + "message": "E: E1 ❌ E2 ❌ E3 ❌ E4 ❌ E5 ❌ E6 ❌ E7 ❌ E8 ❌ E9 ❌ E10 ❌ E11 ❌ E12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "fd972ba6efcfa6e2c423e748b769ae09", + "notes": [], + "params": { + "message": "F: F1 ❌ F2 ❌ F3 ❌ F4 ❌ F5 ❌ F6 ❌ F7 ❌ F8 ❌ F9 ❌ F10 ❌ F11 ❌ F12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "740c240306f144d6eb3f2f37b137ae1f", + "notes": [], + "params": { + "message": "G: G1 ❌ G2 ❌ G3 ❌ G4 ❌ G5 ❌ G6 ❌ G7 ❌ G8 ❌ G9 ❌ G10 ❌ G11 ❌ G12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "ea105a8bc9ec6645a6d993b584bf8369", + "notes": [], + "params": { + "message": "H: H1 ❌ H2 ❌ H3 ❌ H4 ❌ H5 ❌ H6 ❌ H7 ❌ H8 ❌ H9 ❌ H10 ❌ H11 ❌ H12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "liquidProbe", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "5a0d372a3eae37ae4898fc29e7f3840e", + "notes": [], + "params": { + "labwareId": "UUID", + "pipetteId": "UUID", + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": 2.0 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 46.4 + }, + "z_position": 39.55 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "aspirate", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "f39e598e806daf765313a303d0d157ee", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "volume": 5.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -38.55 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 5.85 + }, + "volume": 5.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "moveToWell", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "f909836a4d4875e5ccfeaa5f6c139666", + "notes": [], + "params": { + "forceDirect": false, + "labwareId": "UUID", + "pipetteId": "UUID", + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": 29.999999999999993 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 74.39999999999998 + } + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "aspirate", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "92afd096c372098f64a9bfb0873b355b", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "volume": 995.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": 29.999999999999993 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 74.39999999999998 + }, + "volume": 995.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "moveToAddressableArea", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "ef0781edef6aca01d9879b1a09d9b3f2", + "notes": [], + "params": { + "addressableAreaName": "96ChannelWasteChute", + "forceDirect": false, + "offset": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "pipetteId": "UUID", + "stayAtHighestPossibleZ": false + }, + "result": { + "position": { + "x": 391.945, + "y": 10.585, + "z": 114.5 + } + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "blowOutInPlace", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "af716ae841d9585043867a431d539d55", + "notes": [], + "params": { + "flowRate": 80.0, + "pipetteId": "UUID" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "prepareToAspirate", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "349bb0bf929376ee5a1c92c7882fdacf", + "notes": [], + "params": { + "pipetteId": "UUID" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "liquidProbe", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "66068d631b0410c78ec504b2efd9192f", + "notes": [], + "params": { + "labwareId": "UUID", + "pipetteId": "UUID", + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": 2.0 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 46.4 + }, + "z_position": 39.55 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "aspirate", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "72a351430efa97bacea8b8baa9e67d7a", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "volume": 5.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -38.55 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 5.85 + }, + "volume": 5.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "moveToWell", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "75759431a0a6325eeaf70f09f1541b2f", + "notes": [], + "params": { + "forceDirect": false, + "labwareId": "UUID", + "pipetteId": "UUID", + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": 29.999999999999993 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 74.39999999999998 + } + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "aspirate", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "f40963e7ee5296cada36d22981b64865", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "volume": 995.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": 29.999999999999993 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 74.39999999999998 + }, + "volume": 995.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "moveToAddressableArea", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "ca81c96c5e6706521c28eeb429560dbb", + "notes": [], + "params": { + "addressableAreaName": "96ChannelWasteChute", + "forceDirect": false, + "offset": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "pipetteId": "UUID", + "stayAtHighestPossibleZ": false + }, + "result": { + "position": { + "x": 391.945, + "y": 10.585, + "z": 114.5 + } + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "blowOutInPlace", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "e1d6d21093014d3715ff4f1e41d64add", + "notes": [], + "params": { + "flowRate": 80.0, + "pipetteId": "UUID" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "prepareToAspirate", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "0947370822b6af57af2a7acabdfb1c4d", + "notes": [], + "params": { + "pipetteId": "UUID" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "liquidProbe", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "6f32130e79de0fab3b9694367d1df14d", + "notes": [], + "params": { + "labwareId": "UUID", + "pipetteId": "UUID", + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": 2.0 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 46.4 + }, + "z_position": 39.55 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "aspirate", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "375d7aacf8cfb56bd73ae3fe64eda953", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "volume": 10.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -38.55 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 5.85 + }, + "volume": 10.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "dispense", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "188aead45e3881975f879a62331bf6d9", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "volume": 10.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -13.95 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 178.38, + "y": 181.24, + "z": 2.05 + }, + "volume": 10.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "liquidProbe", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "3c58ecc0dd1bb01b8c561c1a5b8efc79", + "notes": [], + "params": { + "labwareId": "UUID", + "pipetteId": "UUID", + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": 2.0 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 178.38, + "y": 181.24, + "z": 18.0 + }, + "z_position": 14.95 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "aspirate", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "d953a57ea73562ecbb1bb7c46fa516dc", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "volume": 15.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -13.95 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 178.38, + "y": 181.24, + "z": 2.05 + }, + "volume": 15.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "dispense", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "802a4b04ebd2b303f50dd568f841dc2e", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "pushOut": 0.0, + "volume": 15.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -13.95 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 178.38, + "y": 181.24, + "z": 2.05 + }, + "volume": 15.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "aspirate", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "ffcef1be9b48b826f0cc646961192d81", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "volume": 15.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -13.95 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 178.38, + "y": 181.24, + "z": 2.05 + }, + "volume": 15.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "dispense", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "4fb4e8b75e18cb95da915141eb49b7d0", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "pushOut": 0.0, + "volume": 15.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -13.95 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 178.38, + "y": 181.24, + "z": 2.05 + }, + "volume": 15.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "aspirate", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "1c6fe66b1d9cc8a50c94f2818e9bb0c0", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "volume": 15.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -13.95 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 178.38, + "y": 181.24, + "z": 2.05 + }, + "volume": 15.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "dispense", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "05998ba40ade9c08ed03d97aebb538e8", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "pushOut": 0.0, + "volume": 15.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -13.95 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 178.38, + "y": 181.24, + "z": 2.05 + }, + "volume": 15.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "aspirate", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "d0e081f09d5e7358497f152498b7ff67", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "volume": 15.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -13.95 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 178.38, + "y": 181.24, + "z": 2.05 + }, + "volume": 15.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "dispense", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "39a94f9fe6a63daaaef83ccceee0e661", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "pushOut": 0.0, + "volume": 15.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -13.95 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 178.38, + "y": 181.24, + "z": 2.05 + }, + "volume": 15.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "aspirate", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "60db0e75d04bf60b1dde66ad4346214c", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "volume": 15.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -13.95 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 178.38, + "y": 181.24, + "z": 2.05 + }, + "volume": 15.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "dispense", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "54213b7b2f9be52a52f64cf8841a5d83", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "volume": 15.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -13.95 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 178.38, + "y": 181.24, + "z": 2.05 + }, + "volume": 15.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "dropTip", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "56fe165d9f183c0829edd60e88bf9ada", + "notes": [], + "params": { + "alternateDropLocation": false, + "labwareId": "UUID", + "pipetteId": "UUID", + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "origin": "default" + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 178.38, + "y": 395.38, + "z": 90.88 + } + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "9bba35ad84bf2275a6f3298fd03d5187", + "notes": [], + "params": { + "message": "Tip rack in Opentrons Flex 96 Tip Rack Adapter" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "fbe3905bfb62be150cd42317a36f0e8f", + "notes": [], + "params": { + "message": "A: A1 ❌ A2 ❌ A3 ❌ A4 ❌ A5 ❌ A6 ❌ A7 ❌ A8 ❌ A9 ❌ A10 ❌ A11 ❌ A12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "3cc7f1b0fe6b2a8d90591c32ac0c9cde", + "notes": [], + "params": { + "message": "B: B1 ❌ B2 ❌ B3 ❌ B4 ❌ B5 ❌ B6 ❌ B7 ❌ B8 ❌ B9 ❌ B10 ❌ B11 ❌ B12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "a455eac2b6ad82f8c15fd9dda45d8882", + "notes": [], + "params": { + "message": "C: C1 ❌ C2 ❌ C3 ❌ C4 ❌ C5 ❌ C6 ❌ C7 ❌ C8 ❌ C9 ❌ C10 ❌ C11 ❌ C12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "2cd8818343ed0e921367bd42ef1112ee", + "notes": [], + "params": { + "message": "D: D1 ❌ D2 ❌ D3 ❌ D4 ❌ D5 ❌ D6 ❌ D7 ❌ D8 ❌ D9 ❌ D10 ❌ D11 ❌ D12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "f92b8f56db51db3b60599e7b28445a36", + "notes": [], + "params": { + "message": "E: E1 ❌ E2 ❌ E3 ❌ E4 ❌ E5 ❌ E6 ❌ E7 ❌ E8 ❌ E9 ❌ E10 ❌ E11 ❌ E12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "44922a596363eb6844146a36fe3ac517", + "notes": [], + "params": { + "message": "F: F1 ❌ F2 ❌ F3 ❌ F4 ❌ F5 ❌ F6 ❌ F7 ❌ F8 ❌ F9 ❌ F10 ❌ F11 ❌ F12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "3be4bbcb6d53e5eeffb1afa4e8d3a24a", + "notes": [], + "params": { + "message": "G: G1 ❌ G2 ❌ G3 ❌ G4 ❌ G5 ❌ G6 ❌ G7 ❌ G8 ❌ G9 ❌ G10 ❌ G11 ❌ G12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "69ffdab33828b93ec704bdbc413c1737", + "notes": [], + "params": { + "message": "H: H1 ❌ H2 ❌ H3 ❌ H4 ❌ H5 ❌ H6 ❌ H7 ❌ H8 ❌ H9 ❌ H10 ❌ H11 ❌ H12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "pickUpTip", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "555305195a9fa7a6e42458e37a2934e3", + "notes": [], + "params": { + "labwareId": "UUID", + "pipetteId": "UUID", + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "origin": "top" + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 178.38, + "y": 395.38, + "z": 110.0 + }, + "tipDiameter": 5.47, + "tipLength": 85.38999999999999, + "tipVolume": 1000.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "liquidProbe", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "889eee1bbba96644a80db22726b4a69a", + "notes": [], + "params": { + "labwareId": "UUID", + "pipetteId": "UUID", + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": 2.0 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 46.4 + }, + "z_position": 39.55 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "aspirate", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "f72e9c3d813de4285e722ec87c596154", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "volume": 5.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -38.55 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 5.85 + }, + "volume": 5.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "dispense", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "ad48da5e9be4a5df85ddcf8d7184d0c8", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "pushOut": 0.0, + "volume": 5.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -38.55 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 5.85 + }, + "volume": 5.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "aspirate", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "fbdf4b8ac2749cb43d260e15c7b5bdc4", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "volume": 5.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -38.55 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 5.85 + }, + "volume": 5.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "dispense", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "72f42105daee58b1475cf8ecf7a1beb4", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "pushOut": 0.0, + "volume": 5.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -38.55 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 5.85 + }, + "volume": 5.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "aspirate", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "b8d9b6e0d7f61b0fbf64506e479cab62", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "volume": 5.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -38.55 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 5.85 + }, + "volume": 5.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "dispense", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "1e09ac145c0efa97283b7cd9f049edf4", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "volume": 5.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -38.55 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 5.85 + }, + "volume": 5.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "liquidProbe", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "8024e861cc4bf515fb9ca70c4ec8a74b", + "notes": [], + "params": { + "labwareId": "UUID", + "pipetteId": "UUID", + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": 2.0 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 46.4 + }, + "z_position": 39.55 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "aspirate", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "9166539061095ad42ec58573fc8ebd04", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "volume": 10.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -38.55 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 5.85 + }, + "volume": 10.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "dispense", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "2c73b1942409fa2c78c7bae9b7a4fab1", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "volume": 10.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -13.95 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 178.38, + "y": 181.24, + "z": 2.05 + }, + "volume": 10.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "liquidProbe", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "78c817792c844a6b3441b1b214f8add9", + "notes": [], + "params": { + "labwareId": "UUID", + "pipetteId": "UUID", + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": 2.0 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 178.38, + "y": 181.24, + "z": 18.0 + }, + "z_position": 14.95 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "aspirate", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "02130e935d2b1096c98f46562a5a4940", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "volume": 5.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -13.95 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 178.38, + "y": 181.24, + "z": 2.05 + }, + "volume": 5.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "dispense", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "9b374953d929a83ceb00b787065f4749", + "notes": [], + "params": { + "flowRate": 160.0, + "labwareId": "UUID", + "pipetteId": "UUID", + "volume": 5.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -13.95 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 178.38, + "y": 181.24, + "z": 2.05 + }, + "volume": 5.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "touchTip", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "f44c5b4dcf502560454b7c55f86ce207", + "notes": [], + "params": { + "labwareId": "UUID", + "pipetteId": "UUID", + "radius": 1.0, + "speed": 60.0, + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": -1.0 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 178.38, + "y": 181.24, + "z": 15.0 + } + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "moveToAddressableArea", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "396dbf283e4856e439bf95b1464d6774", + "notes": [], + "params": { + "addressableAreaName": "96ChannelWasteChute", + "forceDirect": false, + "offset": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "pipetteId": "UUID", + "stayAtHighestPossibleZ": false + }, + "result": { + "position": { + "x": 391.945, + "y": 10.585, + "z": 114.5 + } + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "blowOutInPlace", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "6bd9b67b490d5fcb1f6f2a5574813599", + "notes": [], + "params": { + "flowRate": 80.0, + "pipetteId": "UUID" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "b12de52c4b99321ce3dd3ebef1ace986", + "notes": [], + "params": { + "message": "Tip rack in Opentrons Flex 96 Tip Rack Adapter" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "e05ac7b430c14364b6f2fdf3dc2af27e", + "notes": [], + "params": { + "message": "A: A1 ❌ A2 ❌ A3 ❌ A4 ❌ A5 ❌ A6 ❌ A7 ❌ A8 ❌ A9 ❌ A10 ❌ A11 ❌ A12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "3cf4c37d88b549ff7edb749d39b12893", + "notes": [], + "params": { + "message": "B: B1 ❌ B2 ❌ B3 ❌ B4 ❌ B5 ❌ B6 ❌ B7 ❌ B8 ❌ B9 ❌ B10 ❌ B11 ❌ B12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "d9d646d906f12bb1c967be93839f7299", + "notes": [], + "params": { + "message": "C: C1 ❌ C2 ❌ C3 ❌ C4 ❌ C5 ❌ C6 ❌ C7 ❌ C8 ❌ C9 ❌ C10 ❌ C11 ❌ C12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "6f55ed54e09f89c01243bb2285cbbf48", + "notes": [], + "params": { + "message": "D: D1 ❌ D2 ❌ D3 ❌ D4 ❌ D5 ❌ D6 ❌ D7 ❌ D8 ❌ D9 ❌ D10 ❌ D11 ❌ D12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "19c19a260d4adfa0c89801870fb888af", + "notes": [], + "params": { + "message": "E: E1 ❌ E2 ❌ E3 ❌ E4 ❌ E5 ❌ E6 ❌ E7 ❌ E8 ❌ E9 ❌ E10 ❌ E11 ❌ E12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "3b29221f75f3b684631085f5297945d7", + "notes": [], + "params": { + "message": "F: F1 ❌ F2 ❌ F3 ❌ F4 ❌ F5 ❌ F6 ❌ F7 ❌ F8 ❌ F9 ❌ F10 ❌ F11 ❌ F12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "04a79ca0387a44d148485363d8825314", + "notes": [], + "params": { + "message": "G: G1 ❌ G2 ❌ G3 ❌ G4 ❌ G5 ❌ G6 ❌ G7 ❌ G8 ❌ G9 ❌ G10 ❌ G11 ❌ G12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "51040551e5ab6544ed7df57e3d31af1c", + "notes": [], + "params": { + "message": "H: H1 ❌ H2 ❌ H3 ❌ H4 ❌ H5 ❌ H6 ❌ H7 ❌ H8 ❌ H9 ❌ H10 ❌ H11 ❌ H12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "dropTip", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "1237ae4e1a24ca35be4422f0f6ce94dd", + "notes": [], + "params": { + "alternateDropLocation": false, + "homeAfter": false, + "labwareId": "UUID", + "pipetteId": "UUID", + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "origin": "default" + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 178.38, + "y": 395.38, + "z": 90.88 + } + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "2807c440b5749ca58f964eea2b0173bd", + "notes": [], + "params": { + "message": "Tip rack in Opentrons Flex 96 Tip Rack Adapter" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "49a6a126b3f1bd562b481b1ed0aa2076", + "notes": [], + "params": { + "message": "A: A1 ❌ A2 ❌ A3 ❌ A4 ❌ A5 ❌ A6 ❌ A7 ❌ A8 ❌ A9 ❌ A10 ❌ A11 ❌ A12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "b28eaed62162a6cba37b2b2adbce3da7", + "notes": [], + "params": { + "message": "B: B1 ❌ B2 ❌ B3 ❌ B4 ❌ B5 ❌ B6 ❌ B7 ❌ B8 ❌ B9 ❌ B10 ❌ B11 ❌ B12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "c23e5efd595af9bd86091d2d55ce4b9a", + "notes": [], + "params": { + "message": "C: C1 ❌ C2 ❌ C3 ❌ C4 ❌ C5 ❌ C6 ❌ C7 ❌ C8 ❌ C9 ❌ C10 ❌ C11 ❌ C12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "07b2576296bc2809caf537d7f7b23e32", + "notes": [], + "params": { + "message": "D: D1 ❌ D2 ❌ D3 ❌ D4 ❌ D5 ❌ D6 ❌ D7 ❌ D8 ❌ D9 ❌ D10 ❌ D11 ❌ D12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "bf247b006b5c8ef36385e4ec56c417c3", + "notes": [], + "params": { + "message": "E: E1 ❌ E2 ❌ E3 ❌ E4 ❌ E5 ❌ E6 ❌ E7 ❌ E8 ❌ E9 ❌ E10 ❌ E11 ❌ E12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "7792788aff047a2c81f5326af7d60612", + "notes": [], + "params": { + "message": "F: F1 ❌ F2 ❌ F3 ❌ F4 ❌ F5 ❌ F6 ❌ F7 ❌ F8 ❌ F9 ❌ F10 ❌ F11 ❌ F12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "c924c03e02674de3e6cb386a3f2a3dd2", + "notes": [], + "params": { + "message": "G: G1 ❌ G2 ❌ G3 ❌ G4 ❌ G5 ❌ G6 ❌ G7 ❌ G8 ❌ G9 ❌ G10 ❌ G11 ❌ G12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "1d51c2a28f6474ff8e1869e842e280ef", + "notes": [], + "params": { + "message": "H: H1 ❌ H2 ❌ H3 ❌ H4 ❌ H5 ❌ H6 ❌ H7 ❌ H8 ❌ H9 ❌ H10 ❌ H11 ❌ H12 ❌ " + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "5f76720ac31bec344907102b24db2587", + "notes": [], + "params": { + "message": "I think the above should not be empty?" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "moveLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "f8aa7b28aea0b80b4fa83831e80ab7c0", + "notes": [], + "params": { + "labwareId": "UUID", + "newLocation": { + "moduleId": "UUID" + }, + "strategy": "usingGripper" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "moveLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "ecca018448f3be0be1d42df4abe64d29", + "notes": [], + "params": { + "labwareId": "UUID", + "newLocation": { + "labwareId": "UUID" + }, + "strategy": "usingGripper" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "thermocycler/closeLid", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "0b8b0a843658fab0070a14b29383d4b6", + "notes": [], + "params": { + "moduleId": "UUID" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "thermocycler/setTargetBlockTemperature", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "5d5f3d5b64948ce5d0442c949b58580d", + "notes": [], + "params": { + "celsius": 38.0, + "holdTimeSeconds": 5.0, + "moduleId": "UUID" + }, + "result": { + "targetBlockTemperature": 38.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "thermocycler/waitForBlockTemperature", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "55f7eea09ff71c6b93b52d15f9b778ba", + "notes": [], + "params": { + "moduleId": "UUID" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "thermocycler/setTargetLidTemperature", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "bd916b6b732fbfe8e2151cdf842d4d77", + "notes": [], + "params": { + "celsius": 38.0, + "moduleId": "UUID" + }, + "result": { + "targetLidTemperature": 38.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "thermocycler/waitForLidTemperature", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "61c47242119c089e39c2970fbb9c5a87", + "notes": [], + "params": { + "moduleId": "UUID" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "thermocycler/openLid", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "26d710513eb567d25ec6c7564178f2f6", + "notes": [], + "params": { + "moduleId": "UUID" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "moveLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "328cffb6ec92cddfdf9b793822084af8", + "notes": [], + "params": { + "labwareId": "UUID", + "newLocation": { + "addressableAreaName": "gripperWasteChute" + }, + "strategy": "usingGripper" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "thermocycler/deactivateBlock", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "a644d2f8960bb1f9ea36838d49796e86", + "notes": [], + "params": { + "moduleId": "UUID" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "thermocycler/deactivateLid", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "04bc1e2c660b9a49ff9b4ae75b2a7530", + "notes": [], + "params": { + "moduleId": "UUID" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "heaterShaker/openLabwareLatch", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "a2c406012e8e618eba18668129dc7210", + "notes": [], + "params": { + "moduleId": "UUID" + }, + "result": { + "pipetteRetracted": true + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "moveLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "7e902c9531e52458c9c1e86eb4fb3bb6", + "notes": [], + "params": { + "labwareId": "UUID", + "newLocation": { + "labwareId": "UUID" + }, + "strategy": "usingGripper" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "heaterShaker/closeLabwareLatch", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "76e684c73a4874bf4e8c3c80ee466258", + "notes": [], + "params": { + "moduleId": "UUID" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "heaterShaker/setTargetTemperature", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "788cd6378d690bb4cb1a55713b109ff4", + "notes": [], + "params": { + "celsius": 38.0, + "moduleId": "UUID" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "heaterShaker/setAndWaitForShakeSpeed", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "866729c2f032edcbb976943d6afed1b8", + "notes": [], + "params": { + "moduleId": "UUID", + "rpm": 777.0 + }, + "result": { + "pipetteRetracted": true + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "heaterShaker/waitForTemperature", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "12e4febccf2785fec55a7cea18901c34", + "notes": [], + "params": { + "moduleId": "UUID" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "heaterShaker/deactivateHeater", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "91146a40c4e7497a9d69be9920689507", + "notes": [], + "params": { + "moduleId": "UUID" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "heaterShaker/deactivateShaker", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "511c2d31b524be9c8c36fba36edf17b6", + "notes": [], + "params": { + "moduleId": "UUID" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "heaterShaker/openLabwareLatch", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "77b87b86baa82a0bdbbee3674ae3778f", + "notes": [], + "params": { + "moduleId": "UUID" + }, + "result": { + "pipetteRetracted": true + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "moveLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "dc518febf332036503375d529f643de2", + "notes": [], + "params": { + "labwareId": "UUID", + "newLocation": { + "labwareId": "UUID" + }, + "strategy": "usingGripper" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "temperatureModule/setTargetTemperature", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "452014b616f7c44e48ae0e0d8ba04d4d", + "notes": [], + "params": { + "celsius": 38.0, + "moduleId": "UUID" + }, + "result": { + "targetTemperature": 38.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "temperatureModule/waitForTemperature", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "4e0d56666b7e4686daedba5eaa6e3bd3", + "notes": [], + "params": { + "moduleId": "UUID" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "temperatureModule/deactivate", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "c6b71690c162eb1d471add58f20491fe", + "notes": [], + "params": { + "moduleId": "UUID" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "moveLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "a9659e82d69a0cb7cb289ca5787195e9", + "notes": [], + "params": { + "labwareId": "UUID", + "newLocation": { + "moduleId": "UUID" + }, + "strategy": "usingGripper" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "absorbanceReader/closeLid", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "365ab2acd2036e30c2b4ba4422301d5f", + "notes": [], + "params": { + "moduleId": "UUID" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "absorbanceReader/read", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "a80b3f4b976053ae6453bc8505b218ce", + "notes": [], + "params": { + "fileName": "smoke_APR_data.csv", + "moduleId": "UUID" + }, + "result": { + "data": { + "600": { + "A1": 0.0, + "A10": 0.0, + "A11": 0.0, + "A12": 0.0, + "A2": 0.0, + "A3": 0.0, + "A4": 0.0, + "A5": 0.0, + "A6": 0.0, + "A7": 0.0, + "A8": 0.0, + "A9": 0.0, + "B1": 0.0, + "B10": 0.0, + "B11": 0.0, + "B12": 0.0, + "B2": 0.0, + "B3": 0.0, + "B4": 0.0, + "B5": 0.0, + "B6": 0.0, + "B7": 0.0, + "B8": 0.0, + "B9": 0.0, + "C1": 0.0, + "C10": 0.0, + "C11": 0.0, + "C12": 0.0, + "C2": 0.0, + "C3": 0.0, + "C4": 0.0, + "C5": 0.0, + "C6": 0.0, + "C7": 0.0, + "C8": 0.0, + "C9": 0.0, + "D1": 0.0, + "D10": 0.0, + "D11": 0.0, + "D12": 0.0, + "D2": 0.0, + "D3": 0.0, + "D4": 0.0, + "D5": 0.0, + "D6": 0.0, + "D7": 0.0, + "D8": 0.0, + "D9": 0.0, + "E1": 0.0, + "E10": 0.0, + "E11": 0.0, + "E12": 0.0, + "E2": 0.0, + "E3": 0.0, + "E4": 0.0, + "E5": 0.0, + "E6": 0.0, + "E7": 0.0, + "E8": 0.0, + "E9": 0.0, + "F1": 0.0, + "F10": 0.0, + "F11": 0.0, + "F12": 0.0, + "F2": 0.0, + "F3": 0.0, + "F4": 0.0, + "F5": 0.0, + "F6": 0.0, + "F7": 0.0, + "F8": 0.0, + "F9": 0.0, + "G1": 0.0, + "G10": 0.0, + "G11": 0.0, + "G12": 0.0, + "G2": 0.0, + "G3": 0.0, + "G4": 0.0, + "G5": 0.0, + "G6": 0.0, + "G7": 0.0, + "G8": 0.0, + "G9": 0.0, + "H1": 0.0, + "H10": 0.0, + "H11": 0.0, + "H12": 0.0, + "H2": 0.0, + "H3": 0.0, + "H4": 0.0, + "H5": 0.0, + "H6": 0.0, + "H7": 0.0, + "H8": 0.0, + "H9": 0.0 + } + }, + "fileIds": [ + "" + ] + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "comment", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "05cfadac7c9a474a7bafe928aee58bf6", + "notes": [], + "params": { + "message": "single: {600: {'A1': 0.0, 'A2': 0.0, 'A3': 0.0, 'A4': 0.0, 'A5': 0.0, 'A6': 0.0, 'A7': 0.0, 'A8': 0.0, 'A9': 0.0, 'A10': 0.0, 'A11': 0.0, 'A12': 0.0, 'B1': 0.0, 'B2': 0.0, 'B3': 0.0, 'B4': 0.0, 'B5': 0.0, 'B6': 0.0, 'B7': 0.0, 'B8': 0.0, 'B9': 0.0, 'B10': 0.0, 'B11': 0.0, 'B12': 0.0, 'C1': 0.0, 'C2': 0.0, 'C3': 0.0, 'C4': 0.0, 'C5': 0.0, 'C6': 0.0, 'C7': 0.0, 'C8': 0.0, 'C9': 0.0, 'C10': 0.0, 'C11': 0.0, 'C12': 0.0, 'D1': 0.0, 'D2': 0.0, 'D3': 0.0, 'D4': 0.0, 'D5': 0.0, 'D6': 0.0, 'D7': 0.0, 'D8': 0.0, 'D9': 0.0, 'D10': 0.0, 'D11': 0.0, 'D12': 0.0, 'E1': 0.0, 'E2': 0.0, 'E3': 0.0, 'E4': 0.0, 'E5': 0.0, 'E6': 0.0, 'E7': 0.0, 'E8': 0.0, 'E9': 0.0, 'E10': 0.0, 'E11': 0.0, 'E12': 0.0, 'F1': 0.0, 'F2': 0.0, 'F3': 0.0, 'F4': 0.0, 'F5': 0.0, 'F6': 0.0, 'F7': 0.0, 'F8': 0.0, 'F9': 0.0, 'F10': 0.0, 'F11': 0.0, 'F12': 0.0, 'G1': 0.0, 'G2': 0.0, 'G3': 0.0, 'G4': 0.0, 'G5': 0.0, 'G6': 0.0, 'G7': 0.0, 'G8': 0.0, 'G9': 0.0, 'G10': 0.0, 'G11': 0.0, 'G12': 0.0, 'H1': 0.0, 'H2': 0.0, 'H3': 0.0, 'H4': 0.0, 'H5': 0.0, 'H6': 0.0, 'H7': 0.0, 'H8': 0.0, 'H9': 0.0, 'H10': 0.0, 'H11': 0.0, 'H12': 0.0}}" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "waitForResume", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "b042e24dd46699520cdedd3f0201ca91", + "notes": [], + "params": { + "message": "single: {600: {'A1': 0.0, 'A2': 0.0, 'A3': 0.0, 'A4': 0.0, 'A5': 0.0, 'A6': 0.0, 'A7': 0.0, 'A8': 0.0, 'A9': 0.0, 'A10': 0.0, 'A11': 0.0, 'A12': 0.0, 'B1': 0.0, 'B2': 0.0, 'B3': 0.0, 'B4': 0.0, 'B5': 0.0, 'B6': 0.0, 'B7': 0.0, 'B8': 0.0, 'B9': 0.0, 'B10': 0.0, 'B11': 0.0, 'B12': 0.0, 'C1': 0.0, 'C2': 0.0, 'C3': 0.0, 'C4': 0.0, 'C5': 0.0, 'C6': 0.0, 'C7': 0.0, 'C8': 0.0, 'C9': 0.0, 'C10': 0.0, 'C11': 0.0, 'C12': 0.0, 'D1': 0.0, 'D2': 0.0, 'D3': 0.0, 'D4': 0.0, 'D5': 0.0, 'D6': 0.0, 'D7': 0.0, 'D8': 0.0, 'D9': 0.0, 'D10': 0.0, 'D11': 0.0, 'D12': 0.0, 'E1': 0.0, 'E2': 0.0, 'E3': 0.0, 'E4': 0.0, 'E5': 0.0, 'E6': 0.0, 'E7': 0.0, 'E8': 0.0, 'E9': 0.0, 'E10': 0.0, 'E11': 0.0, 'E12': 0.0, 'F1': 0.0, 'F2': 0.0, 'F3': 0.0, 'F4': 0.0, 'F5': 0.0, 'F6': 0.0, 'F7': 0.0, 'F8': 0.0, 'F9': 0.0, 'F10': 0.0, 'F11': 0.0, 'F12': 0.0, 'G1': 0.0, 'G2': 0.0, 'G3': 0.0, 'G4': 0.0, 'G5': 0.0, 'G6': 0.0, 'G7': 0.0, 'G8': 0.0, 'G9': 0.0, 'G10': 0.0, 'G11': 0.0, 'G12': 0.0, 'H1': 0.0, 'H2': 0.0, 'H3': 0.0, 'H4': 0.0, 'H5': 0.0, 'H6': 0.0, 'H7': 0.0, 'H8': 0.0, 'H9': 0.0, 'H10': 0.0, 'H11': 0.0, 'H12': 0.0}}" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "absorbanceReader/openLid", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "09edafc3bb1819d89e21f50c773a8b1b", + "notes": [], + "params": { + "moduleId": "UUID" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "moveLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "055de5adcc2476b33f12d303e2f7cd33", + "notes": [], + "params": { + "labwareId": "UUID", + "newLocation": { + "slotName": "C2" + }, + "strategy": "usingGripper" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "moveLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "55fb67ef834deb180669717bbf9bcd08", + "notes": [], + "params": { + "labwareId": "UUID", + "newLocation": "offDeck", + "strategy": "manualMoveWithPause" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "pickUpTip", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "1c42b3e678be0b97d217eda3ba27d0ff", + "notes": [], + "params": { + "labwareId": "UUID", + "pipetteId": "UUID", + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "origin": "top" + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 178.38, + "y": 395.38, + "z": 110.0 + }, + "tipDiameter": 5.47, + "tipLength": 85.38999999999999, + "tipVolume": 1000.0 + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "moveToWell", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "7a9ace3c6ffc32e339e9199029c6e542", + "notes": [], + "params": { + "forceDirect": false, + "labwareId": "UUID", + "pipetteId": "UUID", + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 178.38, + "y": 181.24, + "z": 16.0 + } + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "waitForResume", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "084b51ab7765e9610bb25aad3c5b1420", + "notes": [], + "params": { + "message": "Is the pipette tip in the middle of the PCR Plate, well A1, in slot C2? It should be at the LPC calibrated height." + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "reloadLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "2df58176bd8560ade9f37f43564db735", + "notes": [], + "params": { + "labwareId": "UUID" + }, + "result": { + "labwareId": "UUID", + "offsetId": "UUID" + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "moveToWell", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "bded418ba653fcd22e912654c04201ce", + "notes": [], + "params": { + "forceDirect": false, + "labwareId": "UUID", + "pipetteId": "UUID", + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 178.38, + "y": 181.24, + "z": 26.0 + } + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "waitForResume", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "d24f2277648c132f7aa5610e8afd4a16", + "notes": [], + "params": { + "message": "Is the pipette tip in the middle of the PCR Plate, well A1, in slot C2? It should be 10mm higher than the LPC calibrated height." + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "moveLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "77f86a46915f1f1983f21b7554d629a3", + "notes": [], + "params": { + "labwareId": "UUID", + "newLocation": { + "slotName": "D2" + }, + "strategy": "manualMoveWithPause" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "moveToWell", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "b95e1bdd513812eb0f58b6b868ff95ff", + "notes": [], + "params": { + "forceDirect": false, + "labwareId": "UUID", + "pipetteId": "UUID", + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 178.38, + "y": 74.24, + "z": 16.0 + } + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "waitForResume", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "1fd12fd0b35e829620c353dfa08361b7", + "notes": [], + "params": { + "message": "Is the pipette tip in the middle of the PCR Plate, well A1, in slot D2? It should be at the LPC calibrated height." + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "reloadLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "4b3b80805d46a3dda0c85c4bd3ac65f7", + "notes": [], + "params": { + "labwareId": "UUID" + }, + "result": { + "labwareId": "UUID", + "offsetId": "UUID" + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "moveToWell", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "9283a054c84e7ebfbcafa37fb521bcbb", + "notes": [], + "params": { + "forceDirect": false, + "labwareId": "UUID", + "pipetteId": "UUID", + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 178.38, + "y": 74.24, + "z": 26.0 + } + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "waitForResume", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "8091e40fd9cd4ee7383042b2d7c05138", + "notes": [], + "params": { + "message": "Is the pipette tip in the middle of the PCR Plate, well A1, in slot D2? It should be 10mm higher than the LPC calibrated height." + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "moveLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "3f56958b0a32d667ef60cd9d31c04fd3", + "notes": [], + "params": { + "labwareId": "UUID", + "newLocation": { + "slotName": "C2" + }, + "strategy": "manualMoveWithPause" + }, + "result": { + "offsetId": "UUID" + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "moveToWell", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "853869a39e88a9d5a4d957d55ba28677", + "notes": [], + "params": { + "forceDirect": false, + "labwareId": "UUID", + "pipetteId": "UUID", + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 178.38, + "y": 181.24, + "z": 26.0 + } + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "waitForResume", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "704a3d359b6a341879d4c2a6bee6e5d9", + "notes": [], + "params": { + "message": "Is the pipette tip in the middle of the PCR Plate, well A1, in slot C2? It should be 10mm higher than the LPC calibrated height." + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "moveLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "a0930229a45be6add3b6f59133da1de6", + "notes": [], + "params": { + "labwareId": "UUID", + "newLocation": { + "slotName": "D2" + }, + "strategy": "manualMoveWithPause" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "moveToWell", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "471a6fca269ae526432b1af3abd27b1a", + "notes": [], + "params": { + "forceDirect": false, + "labwareId": "UUID", + "pipetteId": "UUID", + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "origin": "top", + "volumeOffset": 0.0 + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 227.88, + "y": 42.74, + "z": 44.4 + } + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "waitForResume", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "b8898277b6b61116b58e55e0dbb28563", + "notes": [], + "params": { + "message": "Is the pipette tip in the middle of the reservoir , well A1, in slot D2? It should be at the LPC calibrated height." + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "dropTip", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "c92dcade8aedaf07ae1091b486804e95", + "notes": [], + "params": { + "alternateDropLocation": false, + "labwareId": "UUID", + "pipetteId": "UUID", + "wellLocation": { + "offset": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "origin": "default" + }, + "wellName": "A1" + }, + "result": { + "position": { + "x": 178.38, + "y": 395.38, + "z": 90.88 + } + }, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "moveLabware", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "aa312bc19fee7fed08946bfb02cafef4", + "notes": [], + "params": { + "labwareId": "UUID", + "newLocation": { + "addressableAreaName": "gripperWasteChute" + }, + "strategy": "usingGripper" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + }, + { + "commandType": "waitForResume", + "completedAt": "TIMESTAMP", + "createdAt": "TIMESTAMP", + "id": "UUID", + "key": "c9392d146973b6fc471984b1ecea94df", + "notes": [], + "params": { + "message": "!!!!!!!!!!YOU NEED TO REDO LPC!!!!!!!!!!" + }, + "result": {}, + "startedAt": "TIMESTAMP", + "status": "succeeded" + } + ], + "config": { + "apiVersion": [ + 2, + 21 + ], + "protocolType": "python" + }, + "createdAt": "TIMESTAMP", + "errors": [], + "files": [ + { + "name": "Flex_S_v2_21_P1000_96_GRIP_HS_MB_TC_TM_Smoke.py", + "role": "main" + } + ], + "labware": [ + { + "definitionUri": "opentrons/opentrons_flex_deck_riser/1", + "id": "UUID", + "loadName": "opentrons_flex_deck_riser", + "location": { + "addressableAreaName": "A4" + } + }, + { + "definitionUri": "opentrons/opentrons_tough_pcr_auto_sealing_lid/1", + "id": "UUID", + "loadName": "opentrons_tough_pcr_auto_sealing_lid", + "location": { + "labwareId": "UUID" + } + }, + { + "definitionUri": "opentrons/opentrons_tough_pcr_auto_sealing_lid/1", + "id": "UUID", + "loadName": "opentrons_tough_pcr_auto_sealing_lid", + "location": { + "labwareId": "UUID" + } + }, + { + "definitionUri": "opentrons/opentrons_tough_pcr_auto_sealing_lid/1", + "id": "UUID", + "loadName": "opentrons_tough_pcr_auto_sealing_lid", + "location": { + "labwareId": "UUID" + } + }, + { + "definitionUri": "opentrons/opentrons_tough_pcr_auto_sealing_lid/1", + "id": "UUID", + "loadName": "opentrons_tough_pcr_auto_sealing_lid", + "location": { + "labwareId": "UUID" + } + }, + { + "definitionUri": "opentrons/opentrons_tough_pcr_auto_sealing_lid/1", + "id": "UUID", + "loadName": "opentrons_tough_pcr_auto_sealing_lid", + "location": "offDeck" + }, + { + "definitionUri": "opentrons/opentrons_96_well_aluminum_block/1", + "id": "UUID", + "loadName": "opentrons_96_well_aluminum_block", + "location": { + "moduleId": "UUID" + } + }, + { + "definitionUri": "opentrons/opentrons_96_pcr_adapter/1", + "id": "UUID", + "loadName": "opentrons_96_pcr_adapter", + "location": { + "moduleId": "UUID" + } + }, + { + "definitionUri": "opentrons/nest_1_reservoir_290ml/1", + "id": "UUID", + "loadName": "nest_1_reservoir_290ml", + "location": { + "slotName": "D2" + } + }, + { + "definitionUri": "opentrons/opentrons_96_wellplate_200ul_pcr_full_skirt/2", + "id": "UUID", + "loadName": "opentrons_96_wellplate_200ul_pcr_full_skirt", + "location": { + "slotName": "C2" + }, + "offsetId": "UUID" + }, + { + "definitionUri": "opentrons/opentrons_flex_96_tiprack_adapter/1", + "id": "UUID", + "loadName": "opentrons_flex_96_tiprack_adapter", + "location": { + "slotName": "A2" + } + }, + { + "definitionUri": "opentrons/opentrons_flex_96_tiprack_1000ul/1", + "id": "UUID", + "loadName": "opentrons_flex_96_tiprack_1000ul", + "location": { + "labwareId": "UUID" + } + }, + { + "definitionUri": "opentrons/opentrons_flex_96_tiprack_1000ul/1", + "id": "UUID", + "loadName": "opentrons_flex_96_tiprack_1000ul", + "location": "offDeck" + }, + { + "definitionUri": "opentrons/opentrons_flex_96_tiprack_1000ul/1", + "id": "UUID", + "loadName": "opentrons_flex_96_tiprack_1000ul", + "location": "offDeck" + }, + { + "definitionUri": "opentrons/opentrons_flex_96_tiprack_1000ul/1", + "id": "UUID", + "loadName": "opentrons_flex_96_tiprack_1000ul", + "location": "offDeck" + } + ], + "liquidClasses": [], + "liquids": [ + { + "description": "High Quality H₂O", + "displayColor": "#42AB2D", + "displayName": "water", + "id": "UUID" + } + ], + "metadata": { + "author": "QA team", + "protocolName": "Flex Smoke Test - v2.21" + }, + "modules": [ + { + "id": "UUID", + "location": { + "slotName": "B1" + }, + "model": "thermocyclerModuleV2", + "serialNumber": "UUID" + }, + { + "id": "UUID", + "location": { + "slotName": "A3" + }, + "model": "magneticBlockV1" + }, + { + "id": "UUID", + "location": { + "slotName": "C1" + }, + "model": "heaterShakerModuleV1", + "serialNumber": "UUID" + }, + { + "id": "UUID", + "location": { + "slotName": "D1" + }, + "model": "temperatureModuleV2", + "serialNumber": "UUID" + }, + { + "id": "UUID", + "location": { + "slotName": "B3" + }, + "model": "absorbanceReaderV1", + "serialNumber": "UUID" + } + ], + "pipettes": [ + { + "id": "UUID", + "mount": "left", + "pipetteName": "p1000_96" + } + ], + "result": "ok", + "robotType": "OT-3 Standard", + "runTimeParameters": [ + { + "choices": [ + { + "displayName": "Full Smoke Test", + "value": "full" + } + ], + "default": "full", + "description": "Configuration of QA test to perform", + "displayName": "Test Configuration", + "type": "str", + "value": "full", + "variableName": "test_configuration" + }, + { + "choices": [ + { + "displayName": "Nest 1 Well 290 mL", + "value": "nest_1_reservoir_290ml" + } + ], + "default": "nest_1_reservoir_290ml", + "description": "Name of the reservoir", + "displayName": "Reservoir Name", + "type": "str", + "value": "nest_1_reservoir_290ml", + "variableName": "reservoir_name" + }, + { + "choices": [ + { + "displayName": "Opentrons Tough 96 Well 200 µL", + "value": "opentrons_96_wellplate_200ul_pcr_full_skirt" + } + ], + "default": "opentrons_96_wellplate_200ul_pcr_full_skirt", + "description": "Name of the well plate", + "displayName": "Well Plate Name", + "type": "str", + "value": "opentrons_96_wellplate_200ul_pcr_full_skirt", + "variableName": "well_plate_name" + } + ] +} diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[2bc6830494][pl_langone_ribo_pt1_ramp].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[2bc6830494][pl_langone_ribo_pt1_ramp].json index 103852d1fad..cbbda041874 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[2bc6830494][pl_langone_ribo_pt1_ramp].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[2bc6830494][pl_langone_ribo_pt1_ramp].json @@ -4454,6 +4454,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[2eaf98de6a][Flex_S_v2_16_P1000_96_GRIP_HS_MB_TC_TM_TriggerPrepareForMountMovement].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[2eaf98de6a][Flex_S_v2_16_P1000_96_GRIP_HS_MB_TC_TM_TriggerPrepareForMountMovement].json index 527f7681c11..cade2906ff1 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[2eaf98de6a][Flex_S_v2_16_P1000_96_GRIP_HS_MB_TC_TM_TriggerPrepareForMountMovement].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[2eaf98de6a][Flex_S_v2_16_P1000_96_GRIP_HS_MB_TC_TM_TriggerPrepareForMountMovement].json @@ -3757,6 +3757,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[3a039d726f][pl_Dynabeads_IP_Flex_96well_final].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[3a039d726f][pl_Dynabeads_IP_Flex_96well_final].json index 67b6613beee..b38642d42ac 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[3a039d726f][pl_Dynabeads_IP_Flex_96well_final].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[3a039d726f][pl_Dynabeads_IP_Flex_96well_final].json @@ -305,6 +305,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -6191,6 +6196,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[4148613317][Flex_S_v2_19_ligseq].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[4148613317][Flex_S_v2_19_ligseq].json index c25eab4039e..be83efdb3d1 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[4148613317][Flex_S_v2_19_ligseq].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[4148613317][Flex_S_v2_19_ligseq].json @@ -2423,6 +2423,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[42beea80be][pl_96_ch_demo_rtp].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[42beea80be][pl_96_ch_demo_rtp].json index d01d2417596..42f66954c50 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[42beea80be][pl_96_ch_demo_rtp].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[42beea80be][pl_96_ch_demo_rtp].json @@ -3986,6 +3986,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -5265,6 +5270,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[4f50c02c81][Flex_S_v2_19_AMPure_XP_48x].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[4f50c02c81][Flex_S_v2_19_AMPure_XP_48x].json index 953bf5c133d..01407d2b421 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[4f50c02c81][Flex_S_v2_19_AMPure_XP_48x].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[4f50c02c81][Flex_S_v2_19_AMPure_XP_48x].json @@ -4032,6 +4032,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[50d7be4518][pl_Zymo_Quick_RNA_Cells_Flex_multi].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[50d7be4518][pl_Zymo_Quick_RNA_Cells_Flex_multi].json index c22754f270b..00eb89d9c69 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[50d7be4518][pl_Zymo_Quick_RNA_Cells_Flex_multi].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[50d7be4518][pl_Zymo_Quick_RNA_Cells_Flex_multi].json @@ -829,6 +829,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[555b2fff00][Flex_S_v2_19_Illumina_DNA_Prep_48x].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[555b2fff00][Flex_S_v2_19_Illumina_DNA_Prep_48x].json index 10732760f7a..22587a32c81 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[555b2fff00][Flex_S_v2_19_Illumina_DNA_Prep_48x].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[555b2fff00][Flex_S_v2_19_Illumina_DNA_Prep_48x].json @@ -5205,6 +5205,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[59b00713a7][Flex_S_v2_18_ligseq].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[59b00713a7][Flex_S_v2_18_ligseq].json index 17c3ea8b6a4..737dc286bb5 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[59b00713a7][Flex_S_v2_18_ligseq].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[59b00713a7][Flex_S_v2_18_ligseq].json @@ -2423,6 +2423,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[5c57add326][pl_Omega_HDQ_DNA_Bacteria_Flex_96_channel].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[5c57add326][pl_Omega_HDQ_DNA_Bacteria_Flex_96_channel].json index 00ec976bea7..026a1474062 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[5c57add326][pl_Omega_HDQ_DNA_Bacteria_Flex_96_channel].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[5c57add326][pl_Omega_HDQ_DNA_Bacteria_Flex_96_channel].json @@ -829,6 +829,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -2108,6 +2113,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -7979,6 +7989,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -12714,6 +12729,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -15721,6 +15741,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -18728,6 +18753,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -21735,6 +21765,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[63ea171b47][pl_M_N_Nucleomag_DNA_Flex_multi].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[63ea171b47][pl_M_N_Nucleomag_DNA_Flex_multi].json index 36c77e37312..4b86c4eccdc 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[63ea171b47][pl_M_N_Nucleomag_DNA_Flex_multi].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[63ea171b47][pl_M_N_Nucleomag_DNA_Flex_multi].json @@ -829,6 +829,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[6e34343cfc][Flex_S_v2_15_P1000_96_GRIP_HS_MB_TM_MagMaxRNAExtraction].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[6e34343cfc][Flex_S_v2_15_P1000_96_GRIP_HS_MB_TM_MagMaxRNAExtraction].json index 729e4b265eb..5bb400f3266 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[6e34343cfc][Flex_S_v2_15_P1000_96_GRIP_HS_MB_TM_MagMaxRNAExtraction].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[6e34343cfc][Flex_S_v2_15_P1000_96_GRIP_HS_MB_TM_MagMaxRNAExtraction].json @@ -761,6 +761,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -2039,6 +2044,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -5017,6 +5027,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -6295,6 +6310,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -7573,6 +7593,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[6f246e1cd8][Flex_S_2_18_P1000M_P50M_GRIP_HS_TM_MB_TC_IlluminaDNAEnrichmentV4].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[6f246e1cd8][Flex_S_2_18_P1000M_P50M_GRIP_HS_TM_MB_TC_IlluminaDNAEnrichmentV4].json index b2975565a97..a6b46f54c00 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[6f246e1cd8][Flex_S_2_18_P1000M_P50M_GRIP_HS_TM_MB_TC_IlluminaDNAEnrichmentV4].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[6f246e1cd8][Flex_S_2_18_P1000M_P50M_GRIP_HS_TM_MB_TC_IlluminaDNAEnrichmentV4].json @@ -1946,6 +1946,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[70b873c24b][pl_SamplePrep_MS_Digest_Flex_upto96].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[70b873c24b][pl_SamplePrep_MS_Digest_Flex_upto96].json index c62ce072bd9..9afcc19539c 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[70b873c24b][pl_SamplePrep_MS_Digest_Flex_upto96].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[70b873c24b][pl_SamplePrep_MS_Digest_Flex_upto96].json @@ -1600,6 +1600,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[79e61426a2][Flex_S_v2_18_AMPure_XP_48x].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[79e61426a2][Flex_S_v2_18_AMPure_XP_48x].json index ae9a44679de..744032008ce 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[79e61426a2][Flex_S_v2_18_AMPure_XP_48x].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[79e61426a2][Flex_S_v2_18_AMPure_XP_48x].json @@ -4032,6 +4032,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[7d16d5dbf0][Flex_X_v2_21_tc_lids_wrong_target].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[7d16d5dbf0][Flex_X_v2_21_tc_lids_wrong_target].json index ca0539fd2ad..c2da7c45698 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[7d16d5dbf0][Flex_X_v2_21_tc_lids_wrong_target].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[7d16d5dbf0][Flex_X_v2_21_tc_lids_wrong_target].json @@ -830,6 +830,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[7ebefe4580][pl_QIAseq_FX_24x_Normalizer_Workflow_B].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[7ebefe4580][pl_QIAseq_FX_24x_Normalizer_Workflow_B].json index 62f2ce5038d..c567c61d095 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[7ebefe4580][pl_QIAseq_FX_24x_Normalizer_Workflow_B].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[7ebefe4580][pl_QIAseq_FX_24x_Normalizer_Workflow_B].json @@ -857,6 +857,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[84f684cbc4][Flex_S_v2_18_IDT_xGen_EZ_48x].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[84f684cbc4][Flex_S_v2_18_IDT_xGen_EZ_48x].json index edafb62c064..b4e7172cb6c 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[84f684cbc4][Flex_S_v2_18_IDT_xGen_EZ_48x].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[84f684cbc4][Flex_S_v2_18_IDT_xGen_EZ_48x].json @@ -5144,6 +5144,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[88abcfdbca][pl_Zymo_Quick_RNA_Cells_Flex_96_Channel].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[88abcfdbca][pl_Zymo_Quick_RNA_Cells_Flex_96_Channel].json index 080564645c6..d929f2211bb 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[88abcfdbca][pl_Zymo_Quick_RNA_Cells_Flex_96_Channel].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[88abcfdbca][pl_Zymo_Quick_RNA_Cells_Flex_96_Channel].json @@ -829,6 +829,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -6714,6 +6719,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -9721,6 +9731,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -14456,6 +14471,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -17463,6 +17483,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -20470,6 +20495,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -26384,6 +26414,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[8e1f35ed6c][pl_NiNTA_Flex_96well_PlatePrep_final].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[8e1f35ed6c][pl_NiNTA_Flex_96well_PlatePrep_final].json index 37e82771ce7..23a738dea13 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[8e1f35ed6c][pl_NiNTA_Flex_96well_PlatePrep_final].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[8e1f35ed6c][pl_NiNTA_Flex_96well_PlatePrep_final].json @@ -305,6 +305,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -1584,6 +1589,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -2863,6 +2873,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -5195,6 +5210,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[918747b2f9][pl_Illumina_DNA_Prep_48x_v8].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[918747b2f9][pl_Illumina_DNA_Prep_48x_v8].json index 7215d1d2813..4e22ae14eb6 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[918747b2f9][pl_Illumina_DNA_Prep_48x_v8].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[918747b2f9][pl_Illumina_DNA_Prep_48x_v8].json @@ -5205,6 +5205,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[95da6fbef2][Flex_S_2_15_P1000M_GRIP_HS_TM_MB_OmegaHDQDNAExtractionBacteria].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[95da6fbef2][Flex_S_2_15_P1000M_GRIP_HS_TM_MB_OmegaHDQDNAExtractionBacteria].json index 3dc6df75eb5..27170407315 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[95da6fbef2][Flex_S_2_15_P1000M_GRIP_HS_TM_MB_OmegaHDQDNAExtractionBacteria].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[95da6fbef2][Flex_S_2_15_P1000M_GRIP_HS_TM_MB_OmegaHDQDNAExtractionBacteria].json @@ -829,6 +829,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -2108,6 +2113,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -6251,6 +6261,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -7530,6 +7545,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -8809,6 +8829,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -10088,6 +10113,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -11367,6 +11397,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[a0dad2eb8e][pl_SamplePrep_MS_Cleanup_Flex_upto96].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[a0dad2eb8e][pl_SamplePrep_MS_Cleanup_Flex_upto96].json index 65c642d5802..a42786e59e3 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[a0dad2eb8e][pl_SamplePrep_MS_Cleanup_Flex_upto96].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[a0dad2eb8e][pl_SamplePrep_MS_Cleanup_Flex_upto96].json @@ -2124,6 +2124,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -3652,6 +3657,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[a3dfca7f0c][Flex_S_v2_19_Illumina_DNA_PCR_Free].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[a3dfca7f0c][Flex_S_v2_19_Illumina_DNA_PCR_Free].json index 6b9ce6ed6d2..6da5b62e4ec 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[a3dfca7f0c][Flex_S_v2_19_Illumina_DNA_PCR_Free].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[a3dfca7f0c][Flex_S_v2_19_Illumina_DNA_PCR_Free].json @@ -6158,6 +6158,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[a437534569][Flex_S_v2_19_kapahyperplus].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[a437534569][Flex_S_v2_19_kapahyperplus].json index 17c5183316b..814c874d188 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[a437534569][Flex_S_v2_19_kapahyperplus].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[a437534569][Flex_S_v2_19_kapahyperplus].json @@ -6866,6 +6866,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[a46928c103][pl_Nanopore_Genomic_Ligation_v5_Final].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[a46928c103][pl_Nanopore_Genomic_Ligation_v5_Final].json index f022770ef34..8faa3209168 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[a46928c103][pl_Nanopore_Genomic_Ligation_v5_Final].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[a46928c103][pl_Nanopore_Genomic_Ligation_v5_Final].json @@ -2423,6 +2423,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[a4d3b3a2d3][pl_96_ch_demo_rtp_with_hs].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[a4d3b3a2d3][pl_96_ch_demo_rtp_with_hs].json index cb8b6964316..0c84054c2ff 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[a4d3b3a2d3][pl_96_ch_demo_rtp_with_hs].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[a4d3b3a2d3][pl_96_ch_demo_rtp_with_hs].json @@ -4524,6 +4524,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -5803,6 +5808,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[a8a5ad823d][pl_cherrypicking_flex_v3].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[a8a5ad823d][pl_cherrypicking_flex_v3].json index 335d8570804..9be279fa95e 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[a8a5ad823d][pl_cherrypicking_flex_v3].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[a8a5ad823d][pl_cherrypicking_flex_v3].json @@ -1816,6 +1816,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[a94f22054f][Flex_S_v2_18_kapahyperplus].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[a94f22054f][Flex_S_v2_18_kapahyperplus].json index e2cf7a80abc..784df7d0aa1 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[a94f22054f][Flex_S_v2_18_kapahyperplus].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[a94f22054f][Flex_S_v2_18_kapahyperplus].json @@ -6866,6 +6866,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[aa61eee0bf][pl_sigdx_part2].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[aa61eee0bf][pl_sigdx_part2].json index d9080b06e23..6c5410c683b 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[aa61eee0bf][pl_sigdx_part2].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[aa61eee0bf][pl_sigdx_part2].json @@ -763,6 +763,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -2623,6 +2628,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -3901,6 +3911,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[ac5a46e74b][pl_langone_pt2_ribo].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[ac5a46e74b][pl_langone_pt2_ribo].json index 6f5fe499523..f4bafb81e72 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[ac5a46e74b][pl_langone_pt2_ribo].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[ac5a46e74b][pl_langone_pt2_ribo].json @@ -8494,6 +8494,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[ac886d7768][Flex_S_v2_15_P1000_96_GRIP_HS_MB_TC_TM_IDTXgen96Part1to3].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[ac886d7768][Flex_S_v2_15_P1000_96_GRIP_HS_MB_TC_TM_IDTXgen96Part1to3].json index 3436029e76b..b5cf2f13f52 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[ac886d7768][Flex_S_v2_15_P1000_96_GRIP_HS_MB_TC_TM_IDTXgen96Part1to3].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[ac886d7768][Flex_S_v2_15_P1000_96_GRIP_HS_MB_TC_TM_IDTXgen96Part1to3].json @@ -1506,6 +1506,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -4019,6 +4024,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -7698,6 +7708,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -10203,6 +10218,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[b777168ac1][Flex_S_v2_19_Illumina_Stranded_total_RNA_Ribo_Zero].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[b777168ac1][Flex_S_v2_19_Illumina_Stranded_total_RNA_Ribo_Zero].json index 68b2b5c1f76..7fa95382fb8 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[b777168ac1][Flex_S_v2_19_Illumina_Stranded_total_RNA_Ribo_Zero].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[b777168ac1][Flex_S_v2_19_Illumina_Stranded_total_RNA_Ribo_Zero].json @@ -3283,6 +3283,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[b91d31eaa2][pl_MagMax_RNA_Cells_Flex_96_Channel].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[b91d31eaa2][pl_MagMax_RNA_Cells_Flex_96_Channel].json index 4157d11e090..9256b703b2c 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[b91d31eaa2][pl_MagMax_RNA_Cells_Flex_96_Channel].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[b91d31eaa2][pl_MagMax_RNA_Cells_Flex_96_Channel].json @@ -829,6 +829,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -6714,6 +6719,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -8024,6 +8034,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -11031,6 +11046,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -14038,6 +14058,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -17045,6 +17070,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[c8d2ca0089][Flex_S_v2_18_QIASeq_FX_48x].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[c8d2ca0089][Flex_S_v2_18_QIASeq_FX_48x].json index 6c54624f311..c7cc6586b5d 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[c8d2ca0089][Flex_S_v2_18_QIASeq_FX_48x].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[c8d2ca0089][Flex_S_v2_18_QIASeq_FX_48x].json @@ -5144,6 +5144,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[d14738bdfe][pl_Zymo_Magbead_DNA_Cells_Flex_multi].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[d14738bdfe][pl_Zymo_Magbead_DNA_Cells_Flex_multi].json index 14a7616b697..c8f00ac080e 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[d14738bdfe][pl_Zymo_Magbead_DNA_Cells_Flex_multi].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[d14738bdfe][pl_Zymo_Magbead_DNA_Cells_Flex_multi].json @@ -829,6 +829,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[d29d74d7fb][pl_QIASeq_FX_48x_v8].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[d29d74d7fb][pl_QIASeq_FX_48x_v8].json index 9cb48b08976..a9306a86942 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[d29d74d7fb][pl_QIASeq_FX_48x_v8].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[d29d74d7fb][pl_QIASeq_FX_48x_v8].json @@ -5144,6 +5144,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[d391213095][Flex_S_v2_15_P1000_96_GRIP_HS_TM_QuickZymoMagbeadRNAExtractionCellsOrBacteria].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[d391213095][Flex_S_v2_15_P1000_96_GRIP_HS_TM_QuickZymoMagbeadRNAExtractionCellsOrBacteria].json index 2523a86633a..426c94558c1 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[d391213095][Flex_S_v2_15_P1000_96_GRIP_HS_TM_QuickZymoMagbeadRNAExtractionCellsOrBacteria].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[d391213095][Flex_S_v2_15_P1000_96_GRIP_HS_TM_QuickZymoMagbeadRNAExtractionCellsOrBacteria].json @@ -829,6 +829,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -4972,6 +4977,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -6251,6 +6261,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -7530,6 +7545,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -8809,6 +8829,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -10088,6 +10113,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -11367,6 +11397,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[d3b28ea1d7][pl_Zymo_Magbead_DNA_Cells_Flex_96_channel].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[d3b28ea1d7][pl_Zymo_Magbead_DNA_Cells_Flex_96_channel].json index 90e2c5c4dfb..9214cce5922 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[d3b28ea1d7][pl_Zymo_Magbead_DNA_Cells_Flex_96_channel].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[d3b28ea1d7][pl_Zymo_Magbead_DNA_Cells_Flex_96_channel].json @@ -829,6 +829,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -4972,6 +4977,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -9707,6 +9717,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -14442,6 +14457,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -17449,6 +17469,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -20456,6 +20481,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -23463,6 +23493,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[d61739e6a3][Flex_S_v2_19_IDT_xGen_EZ_48x].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[d61739e6a3][Flex_S_v2_19_IDT_xGen_EZ_48x].json index 48cb632ccd4..a8f00e1a0f1 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[d61739e6a3][Flex_S_v2_19_IDT_xGen_EZ_48x].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[d61739e6a3][Flex_S_v2_19_IDT_xGen_EZ_48x].json @@ -5144,6 +5144,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[d6389183c0][pl_AMPure_XP_48x_v8].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[d6389183c0][pl_AMPure_XP_48x_v8].json index 1310283b324..a19d8ed0c76 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[d6389183c0][pl_AMPure_XP_48x_v8].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[d6389183c0][pl_AMPure_XP_48x_v8].json @@ -4032,6 +4032,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[da326082e1][pl_Hyperplus_tiptracking_V4_final].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[da326082e1][pl_Hyperplus_tiptracking_V4_final].json index 47372d63a60..b3678fd89b2 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[da326082e1][pl_Hyperplus_tiptracking_V4_final].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[da326082e1][pl_Hyperplus_tiptracking_V4_final].json @@ -6866,6 +6866,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[e0b0133ffb][pl_Illumina_Stranded_total_RNA_Ribo_Zero_protocol].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[e0b0133ffb][pl_Illumina_Stranded_total_RNA_Ribo_Zero_protocol].json index dba92ac69c0..590ca209392 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[e0b0133ffb][pl_Illumina_Stranded_total_RNA_Ribo_Zero_protocol].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[e0b0133ffb][pl_Illumina_Stranded_total_RNA_Ribo_Zero_protocol].json @@ -3283,6 +3283,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[e4b5b30b2e][Flex_S_v2_18_Illumina_DNA_PCR_Free].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[e4b5b30b2e][Flex_S_v2_18_Illumina_DNA_PCR_Free].json index 881892ce99c..4459fe971fd 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[e4b5b30b2e][Flex_S_v2_18_Illumina_DNA_PCR_Free].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[e4b5b30b2e][Flex_S_v2_18_Illumina_DNA_PCR_Free].json @@ -6158,6 +6158,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[e71b031f47][pl_Illumina_DNA_PCR_Free].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[e71b031f47][pl_Illumina_DNA_PCR_Free].json index 94c209d56fb..cffdb1bb54c 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[e71b031f47][pl_Illumina_DNA_PCR_Free].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[e71b031f47][pl_Illumina_DNA_PCR_Free].json @@ -6158,6 +6158,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[f24bb0b4d9][Flex_S_v2_15_P1000_96_GRIP_HS_MB_TC_TM_IlluminaDNAPrep96PART3].json b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[f24bb0b4d9][Flex_S_v2_15_P1000_96_GRIP_HS_MB_TC_TM_IlluminaDNAPrep96PART3].json index bcc3989e9f6..1c7b1c8237d 100644 --- a/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[f24bb0b4d9][Flex_S_v2_15_P1000_96_GRIP_HS_MB_TC_TM_IlluminaDNAPrep96PART3].json +++ b/analyses-snapshot-testing/tests/__snapshots__/analyses_snapshot_test/test_analysis_snapshot[f24bb0b4d9][Flex_S_v2_15_P1000_96_GRIP_HS_MB_TC_TM_IlluminaDNAPrep96PART3].json @@ -4870,6 +4870,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -6148,6 +6153,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -9943,6 +9953,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, @@ -11221,6 +11236,11 @@ }, "schemaVersion": 2, "stackingOffsetWithLabware": { + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 + }, "opentrons_96_deep_well_adapter": { "x": 0, "y": 0, diff --git a/api/release-notes.md b/api/release-notes.md index 1fdd9a033d9..68d84b62cce 100644 --- a/api/release-notes.md +++ b/api/release-notes.md @@ -8,6 +8,22 @@ By installing and using Opentrons software, you agree to the Opentrons End-User --- +## Opentrons Robot Software Changes in 8.3.0 + +Welcome to the v8.3.0 release of the Opentrons robot software! This release adds support for Evosep Evotips on the Flex, as well as other features. + +### New Features + +- Use Evosep Evotips in Python API version 2.22 protocols for protein sample purification. Only available with the Flex 96-channel pipette. + +- Load a newly modified Flex 8-Channel EM 1000 µL pipette equipped with a PEEK motor component to automate emulsion applications. + +### Improved Features + +- Improvements to the Flex error recovery feature help protocols recover from detected stalls and collisions, saving you valuable time and resources. + +--- + ## Opentrons Robot Software Changes in 8.2.0 Welcome to the v8.2.0 release of the Opentrons robot software! This release adds support for the Opentrons Absorbance Plate Reader Module. diff --git a/api/src/opentrons/hardware_control/api.py b/api/src/opentrons/hardware_control/api.py index a5dbae274fb..6da38ceda0b 100644 --- a/api/src/opentrons/hardware_control/api.py +++ b/api/src/opentrons/hardware_control/api.py @@ -778,6 +778,7 @@ async def move_axes( position: Mapping[Axis, float], speed: Optional[float] = None, max_speeds: Optional[Dict[Axis, float]] = None, + expect_stalls: bool = False, ) -> None: """Moves the effectors of the specified axis to the specified position. The effector of the x,y axis is the center of the carriage. @@ -1250,7 +1251,10 @@ async def pick_up_tip( await self.prepare_for_aspirate(mount) async def tip_drop_moves( - self, mount: top_types.Mount, home_after: bool = True + self, + mount: top_types.Mount, + home_after: bool = True, + ignore_plunger: bool = False, ) -> None: spec, _ = self.plan_check_drop_tip(mount, home_after) diff --git a/api/src/opentrons/hardware_control/ot3api.py b/api/src/opentrons/hardware_control/ot3api.py index bf59793d9dc..a9d61a9f5cc 100644 --- a/api/src/opentrons/hardware_control/ot3api.py +++ b/api/src/opentrons/hardware_control/ot3api.py @@ -1189,7 +1189,7 @@ async def move_to( speed: Optional[float] = None, critical_point: Optional[CriticalPoint] = None, max_speeds: Union[None, Dict[Axis, float], OT3AxisMap[float]] = None, - _expect_stalls: bool = False, + expect_stalls: bool = False, ) -> None: """Move the critical point of the specified mount to a location relative to the deck, at the specified speed.""" @@ -1233,7 +1233,7 @@ async def move_to( target_position, speed=speed, max_speeds=checked_max, - expect_stalls=_expect_stalls, + expect_stalls=expect_stalls, ) async def move_axes( # noqa: C901 @@ -1241,6 +1241,7 @@ async def move_axes( # noqa: C901 position: Mapping[Axis, float], speed: Optional[float] = None, max_speeds: Optional[Dict[Axis, float]] = None, + expect_stalls: bool = False, ) -> None: """Moves the effectors of the specified axis to the specified position. The effector of the x,y axis is the center of the carriage. @@ -1296,7 +1297,11 @@ async def move_axes( # noqa: C901 if axis not in absolute_positions: absolute_positions[axis] = position_value - await self._move(target_position=absolute_positions, speed=speed) + await self._move( + target_position=absolute_positions, + speed=speed, + expect_stalls=expect_stalls, + ) async def move_rel( self, @@ -1306,7 +1311,7 @@ async def move_rel( max_speeds: Union[None, Dict[Axis, float], OT3AxisMap[float]] = None, check_bounds: MotionChecks = MotionChecks.NONE, fail_on_not_homed: bool = False, - _expect_stalls: bool = False, + expect_stalls: bool = False, ) -> None: """Move the critical point of the specified mount by a specified displacement in a specified direction, at the specified speed.""" @@ -1348,7 +1353,7 @@ async def move_rel( speed=speed, max_speeds=checked_max, check_bounds=check_bounds, - expect_stalls=_expect_stalls, + expect_stalls=expect_stalls, ) async def _cache_and_maybe_retract_mount(self, mount: OT3Mount) -> None: @@ -2329,11 +2334,16 @@ def set_working_volume( instrument.working_volume = tip_volume async def tip_drop_moves( - self, mount: Union[top_types.Mount, OT3Mount], home_after: bool = False + self, + mount: Union[top_types.Mount, OT3Mount], + home_after: bool = False, + ignore_plunger: bool = False, ) -> None: realmount = OT3Mount.from_mount(mount) - - await self._move_to_plunger_bottom(realmount, rate=1.0, check_current_vol=False) + if ignore_plunger is False: + await self._move_to_plunger_bottom( + realmount, rate=1.0, check_current_vol=False + ) if self.gantry_load == GantryLoad.HIGH_THROUGHPUT: spec = self._pipette_handler.plan_ht_drop_tip() diff --git a/api/src/opentrons/hardware_control/protocols/liquid_handler.py b/api/src/opentrons/hardware_control/protocols/liquid_handler.py index 045a21795ea..220c4bc9019 100644 --- a/api/src/opentrons/hardware_control/protocols/liquid_handler.py +++ b/api/src/opentrons/hardware_control/protocols/liquid_handler.py @@ -187,7 +187,10 @@ async def pick_up_tip( ... async def tip_drop_moves( - self, mount: MountArgType, home_after: bool = True + self, + mount: MountArgType, + home_after: bool = True, + ignore_plunger: bool = False, ) -> None: ... diff --git a/api/src/opentrons/hardware_control/protocols/motion_controller.py b/api/src/opentrons/hardware_control/protocols/motion_controller.py index e95a9d2e24f..77f78506506 100644 --- a/api/src/opentrons/hardware_control/protocols/motion_controller.py +++ b/api/src/opentrons/hardware_control/protocols/motion_controller.py @@ -171,6 +171,7 @@ async def move_axes( position: Mapping[Axis, float], speed: Optional[float] = None, max_speeds: Optional[Dict[Axis, float]] = None, + expect_stalls: bool = False, ) -> None: """Moves the effectors of the specified axis to the specified position. The effector of the x,y axis is the center of the carriage. diff --git a/api/src/opentrons/legacy_commands/commands.py b/api/src/opentrons/legacy_commands/commands.py index 68b6f1a0595..fbbb14d7fc4 100755 --- a/api/src/opentrons/legacy_commands/commands.py +++ b/api/src/opentrons/legacy_commands/commands.py @@ -299,3 +299,40 @@ def move_to_disposal_location( "name": command_types.MOVE_TO_DISPOSAL_LOCATION, "payload": {"instrument": instrument, "location": location, "text": text}, } + + +def seal( + instrument: InstrumentContext, + location: Well, +) -> command_types.SealCommand: + location_text = stringify_location(location) + text = f"Sealing to {location_text}" + return { + "name": command_types.SEAL, + "payload": {"instrument": instrument, "location": location, "text": text}, + } + + +def unseal( + instrument: InstrumentContext, + location: Well, +) -> command_types.UnsealCommand: + location_text = stringify_location(location) + text = f"Unsealing from {location_text}" + return { + "name": command_types.UNSEAL, + "payload": {"instrument": instrument, "location": location, "text": text}, + } + + +def resin_tip_dispense( + instrument: InstrumentContext, + flow_rate: float | None, +) -> command_types.PressurizeCommand: + if flow_rate is None: + flow_rate = 10 # The Protocol Engine default for Resin Tip Dispense + text = f"Pressurize pipette to dispense from resin tip at {flow_rate}uL/s." + return { + "name": command_types.PRESSURIZE, + "payload": {"instrument": instrument, "text": text}, + } diff --git a/api/src/opentrons/legacy_commands/types.py b/api/src/opentrons/legacy_commands/types.py index 5aaa72b8e09..61302985c2c 100755 --- a/api/src/opentrons/legacy_commands/types.py +++ b/api/src/opentrons/legacy_commands/types.py @@ -43,6 +43,10 @@ RETURN_TIP: Final = "command.RETURN_TIP" MOVE_TO: Final = "command.MOVE_TO" MOVE_TO_DISPOSAL_LOCATION: Final = "command.MOVE_TO_DISPOSAL_LOCATION" +SEAL: Final = "command.SEAL" +UNSEAL: Final = "command.UNSEAL" +PRESSURIZE: Final = "command.PRESSURIZE" + # Modules # @@ -535,11 +539,40 @@ class MoveLabwareCommandPayload(TextOnlyPayload): pass +class SealCommandPayload(TextOnlyPayload): + instrument: InstrumentContext + location: Union[None, Location, Well] + + +class UnsealCommandPayload(TextOnlyPayload): + instrument: InstrumentContext + location: Union[None, Location, Well] + + +class PressurizeCommandPayload(TextOnlyPayload): + instrument: InstrumentContext + + class MoveLabwareCommand(TypedDict): name: Literal["command.MOVE_LABWARE"] payload: MoveLabwareCommandPayload +class SealCommand(TypedDict): + name: Literal["command.SEAL"] + payload: SealCommandPayload + + +class UnsealCommand(TypedDict): + name: Literal["command.UNSEAL"] + payload: UnsealCommandPayload + + +class PressurizeCommand(TypedDict): + name: Literal["command.PRESSURIZE"] + payload: PressurizeCommandPayload + + Command = Union[ DropTipCommand, DropTipInDisposalLocationCommand, @@ -588,6 +621,9 @@ class MoveLabwareCommand(TypedDict): MoveToCommand, MoveToDisposalLocationCommand, MoveLabwareCommand, + SealCommand, + UnsealCommand, + PressurizeCommand, ] @@ -637,6 +673,9 @@ class MoveLabwareCommand(TypedDict): MoveToCommandPayload, MoveToDisposalLocationCommandPayload, MoveLabwareCommandPayload, + SealCommandPayload, + UnsealCommandPayload, + PressurizeCommandPayload, ] diff --git a/api/src/opentrons/protocol_api/core/engine/instrument.py b/api/src/opentrons/protocol_api/core/engine/instrument.py index d1898e5ccaa..7f23bc3d173 100644 --- a/api/src/opentrons/protocol_api/core/engine/instrument.py +++ b/api/src/opentrons/protocol_api/core/engine/instrument.py @@ -61,6 +61,8 @@ from opentrons.protocol_api._liquid_properties import TransferProperties _DISPENSE_VOLUME_VALIDATION_ADDED_IN = APIVersion(2, 17) +_RESIN_TIP_DEFAULT_VOLUME = 400 +_RESIN_TIP_DEFAULT_FLOW_RATE = 10.0 _FLEX_PIPETTE_NAMES_FIXED_IN = APIVersion(2, 23) """The version after which InstrumentContext.name returns the correct API-specific names of Flex pipettes.""" @@ -713,6 +715,113 @@ def move_to( location=location, mount=self.get_mount() ) + def resin_tip_seal( + self, location: Location, well_core: WellCore, in_place: Optional[bool] = False + ) -> None: + labware_id = well_core.labware_id + well_name = well_core.get_name() + well_location = ( + self._engine_client.state.geometry.get_relative_pick_up_tip_well_location( + labware_id=labware_id, + well_name=well_name, + absolute_point=location.point, + ) + ) + + self._engine_client.execute_command( + cmd.EvotipSealPipetteParams( + pipetteId=self._pipette_id, + labwareId=labware_id, + wellName=well_name, + wellLocation=well_location, + ) + ) + + def resin_tip_unseal(self, location: Location, well_core: WellCore) -> None: + well_name = well_core.get_name() + labware_id = well_core.labware_id + + if location is not None: + relative_well_location = ( + self._engine_client.state.geometry.get_relative_well_location( + labware_id=labware_id, + well_name=well_name, + absolute_point=location.point, + ) + ) + + well_location = DropTipWellLocation( + origin=DropTipWellOrigin(relative_well_location.origin.value), + offset=relative_well_location.offset, + ) + else: + well_location = DropTipWellLocation() + + pipette_movement_conflict.check_safe_for_pipette_movement( + engine_state=self._engine_client.state, + pipette_id=self._pipette_id, + labware_id=labware_id, + well_name=well_name, + well_location=well_location, + ) + self._engine_client.execute_command( + cmd.EvotipUnsealPipetteParams( + pipetteId=self._pipette_id, + labwareId=labware_id, + wellName=well_name, + wellLocation=well_location, + ) + ) + + self._protocol_core.set_last_location(location=location, mount=self.get_mount()) + + def resin_tip_dispense( + self, + location: Location, + well_core: WellCore, + volume: Optional[float] = None, + flow_rate: Optional[float] = None, + ) -> None: + """ + Args: + volume: The volume of liquid to dispense, in microliters. Defaults to 400uL. + location: The exact location to dispense to. + well_core: The well to dispense to, if applicable. + flow_rate: The flow rate in µL/s to dispense at. Defaults to 10.0uL/S. + """ + if isinstance(location, (TrashBin, WasteChute)): + raise ValueError("Trash Bin and Waste Chute have no Wells.") + well_name = well_core.get_name() + labware_id = well_core.labware_id + if volume is None: + volume = _RESIN_TIP_DEFAULT_VOLUME + if flow_rate is None: + flow_rate = _RESIN_TIP_DEFAULT_FLOW_RATE + + well_location = self._engine_client.state.geometry.get_relative_liquid_handling_well_location( + labware_id=labware_id, + well_name=well_name, + absolute_point=location.point, + is_meniscus=None, + ) + pipette_movement_conflict.check_safe_for_pipette_movement( + engine_state=self._engine_client.state, + pipette_id=self._pipette_id, + labware_id=labware_id, + well_name=well_name, + well_location=well_location, + ) + self._engine_client.execute_command( + cmd.EvotipDispenseParams( + pipetteId=self._pipette_id, + labwareId=labware_id, + wellName=well_name, + wellLocation=well_location, + volume=volume, + flowRate=flow_rate, + ) + ) + def get_mount(self) -> Mount: """Get the mount the pipette is attached to.""" return self._engine_client.state.pipettes.get( diff --git a/api/src/opentrons/protocol_api/core/instrument.py b/api/src/opentrons/protocol_api/core/instrument.py index 4a60cf8f19e..e3b2844df59 100644 --- a/api/src/opentrons/protocol_api/core/instrument.py +++ b/api/src/opentrons/protocol_api/core/instrument.py @@ -189,6 +189,33 @@ def move_to( ) -> None: ... + @abstractmethod + def resin_tip_seal( + self, + location: types.Location, + well_core: WellCoreType, + in_place: Optional[bool] = False, + ) -> None: + ... + + @abstractmethod + def resin_tip_unseal( + self, + location: types.Location, + well_core: WellCoreType, + ) -> None: + ... + + @abstractmethod + def resin_tip_dispense( + self, + location: types.Location, + well_core: WellCoreType, + volume: Optional[float] = None, + flow_rate: Optional[float] = None, + ) -> None: + ... + @abstractmethod def get_mount(self) -> types.Mount: ... diff --git a/api/src/opentrons/protocol_api/core/legacy/legacy_instrument_core.py b/api/src/opentrons/protocol_api/core/legacy/legacy_instrument_core.py index 5572ef440d9..512bbc06c26 100644 --- a/api/src/opentrons/protocol_api/core/legacy/legacy_instrument_core.py +++ b/api/src/opentrons/protocol_api/core/legacy/legacy_instrument_core.py @@ -318,6 +318,30 @@ def drop_tip_in_disposal_location( ) -> None: raise APIVersionError(api_element="Dropping tips in a trash bin or waste chute") + def resin_tip_seal( + self, + location: types.Location, + well_core: WellCore, + in_place: Optional[bool] = False, + ) -> None: + raise APIVersionError(api_element="Sealing resin tips.") + + def resin_tip_unseal( + self, + location: types.Location, + well_core: WellCore, + ) -> None: + raise APIVersionError(api_element="Unsealing resin tips.") + + def resin_tip_dispense( + self, + location: types.Location, + well_core: WellCore, + volume: Optional[float] = None, + flow_rate: Optional[float] = None, + ) -> None: + raise APIVersionError(api_element="Dispensing liquid from resin tips.") + def home(self) -> None: """Home the mount""" self._protocol_interface.get_hardware().home_z( @@ -410,6 +434,32 @@ def move_to( location=location, mount=location_cache_mount ) + def evotip_seal( + self, + location: types.Location, + well_core: LegacyWellCore, + in_place: Optional[bool] = False, + ) -> None: + """This will never be called because it was added in API 2.22.""" + assert False, "evotip_seal only supported in API 2.22 & later" + + def evotip_unseal( + self, location: types.Location, well_core: WellCore, home_after: Optional[bool] + ) -> None: + """This will never be called because it was added in API 2.22.""" + assert False, "evotip_unseal only supported in API 2.22 & later" + + def evotip_dispense( + self, + location: types.Location, + well_core: WellCore, + volume: Optional[float] = None, + flow_rate: Optional[float] = None, + push_out: Optional[float] = None, + ) -> None: + """This will never be called because it was added in API 2.22.""" + assert False, "evotip_dispense only supported in API 2.22 & later" + def get_mount(self) -> types.Mount: """Get the mount this pipette is attached to.""" return self._mount diff --git a/api/src/opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py b/api/src/opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py index 8c2c570ad1c..d9c5c9c157d 100644 --- a/api/src/opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +++ b/api/src/opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py @@ -286,6 +286,30 @@ def drop_tip_in_disposal_location( ) -> None: raise APIVersionError(api_element="Dropping tips in a trash bin or waste chute") + def resin_tip_seal( + self, + location: types.Location, + well_core: WellCore, + in_place: Optional[bool] = False, + ) -> None: + raise APIVersionError(api_element="Sealing resin tips.") + + def resin_tip_unseal( + self, + location: types.Location, + well_core: WellCore, + ) -> None: + raise APIVersionError(api_element="Unsealing resin tips.") + + def resin_tip_dispense( + self, + location: types.Location, + well_core: WellCore, + volume: Optional[float] = None, + flow_rate: Optional[float] = None, + ) -> None: + raise APIVersionError(api_element="Dispensing liquid from resin tips.") + def home(self) -> None: self._protocol_interface.set_last_location(None) diff --git a/api/src/opentrons/protocol_api/instrument_context.py b/api/src/opentrons/protocol_api/instrument_context.py index 992aa68c785..6a9c5bd5899 100644 --- a/api/src/opentrons/protocol_api/instrument_context.py +++ b/api/src/opentrons/protocol_api/instrument_context.py @@ -1859,6 +1859,147 @@ def move_to( return self + @requires_version(2, 22) + def resin_tip_seal( + self, + location: Union[labware.Well, labware.Labware], + ) -> InstrumentContext: + """Seal resin tips onto the pipette. + + The location provided should contain resin tips. Sealing the + tip will perform a `pick up` action but there will be no tip tracking + associated with the pipette. + + :param location: A location containing resin tips, must be a Labware or a Well. + + :type location: :py:class:`~.types.Location` + """ + if isinstance(location, labware.Labware): + well = location.wells()[0] + else: + well = location + + with publisher.publish_context( + broker=self.broker, + command=cmds.seal( + instrument=self, + location=well, + ), + ): + self._core.resin_tip_seal( + location=well.top(), well_core=well._core, in_place=False + ) + return self + + @requires_version(2, 22) + def resin_tip_unseal( + self, + location: Union[labware.Well, labware.Labware], + ) -> InstrumentContext: + """Release resin tips from the pipette. + + The location provided should be a valid location to drop resin tips. + + :param location: A location containing that can accept tips. + + :type location: :py:class:`~.types.Location` + + :param home_after: + Whether to home the pipette after dropping the tip. If not specified + defaults to ``True`` on a Flex. The plunger will not home on an unseal. + + When ``False``, the pipette does not home its plunger. This can save a few + seconds, but is not recommended. Homing helps the robot track the pipette's + position. + + """ + if isinstance(location, labware.Labware): + well = location.wells()[0] + else: + well = location + + with publisher.publish_context( + broker=self.broker, + command=cmds.unseal( + instrument=self, + location=well, + ), + ): + self._core.resin_tip_unseal(location=well.top(), well_core=well._core) + + return self + + @requires_version(2, 22) + def resin_tip_dispense( + self, + location: types.Location, + volume: Optional[float] = None, + rate: Optional[float] = None, + ) -> InstrumentContext: + """Dispense a volume from resin tips into a labware. + + The location provided should contain resin tips labware as well as a + receptical for dispensed liquid. Dispensing from tip will perform a + `dispense` action of the specified volume at a desired flow rate. + + :param location: A location containing resin tips. + :type location: :py:class:`~.types.Location` + + :param volume: Will default to maximum, recommended to use the default. + The volume, in µL, that the pipette will prepare to handle. + :type volume: float + + :param rate: Will default to 10.0, recommended to use the default. How quickly + a pipette dispenses liquid. The speed in µL/s is calculated as + ``rate`` multiplied by :py:attr:`flow_rate.dispense`. + :type rate: float + + """ + well: Optional[labware.Well] = None + last_location = self._get_last_location_by_api_version() + + try: + target = validation.validate_location( + location=location, last_location=last_location + ) + except validation.NoLocationError as e: + raise RuntimeError( + "If dispense is called without an explicit location, another" + " method that moves to a location (such as move_to or " + "aspirate) must previously have been called so the robot " + "knows where it is." + ) from e + + if isinstance(target, validation.WellTarget): + well = target.well + if target.location: + move_to_location = target.location + elif well.parent._core.is_fixed_trash(): + move_to_location = target.well.top() + else: + move_to_location = target.well.bottom( + z=self._well_bottom_clearances.dispense + ) + else: + raise RuntimeError( + "A well must be specified when using `resin_tip_dispense`." + ) + + with publisher.publish_context( + broker=self.broker, + command=cmds.resin_tip_dispense( + instrument=self, + flow_rate=rate, + ), + ): + self._core.resin_tip_dispense( + move_to_location, + well_core=well._core, + volume=volume, + flow_rate=rate, + ) + return self + @requires_version(2, 18) def _retract( self, diff --git a/api/src/opentrons/protocol_engine/commands/__init__.py b/api/src/opentrons/protocol_engine/commands/__init__.py index e56e3da3b38..a3f78c220fc 100644 --- a/api/src/opentrons/protocol_engine/commands/__init__.py +++ b/api/src/opentrons/protocol_engine/commands/__init__.py @@ -397,6 +397,28 @@ TryLiquidProbeCommandType, ) +from .evotip_seal_pipette import ( + EvotipSealPipette, + EvotipSealPipetteParams, + EvotipSealPipetteCreate, + EvotipSealPipetteResult, + EvotipSealPipetteCommandType, +) +from .evotip_unseal_pipette import ( + EvotipUnsealPipette, + EvotipUnsealPipetteParams, + EvotipUnsealPipetteCreate, + EvotipUnsealPipetteResult, + EvotipUnsealPipetteCommandType, +) +from .evotip_dispense import ( + EvotipDispense, + EvotipDispenseParams, + EvotipDispenseCreate, + EvotipDispenseResult, + EvotipDispenseCommandType, +) + __all__ = [ # command type unions "Command", @@ -700,4 +722,22 @@ "TryLiquidProbeCreate", "TryLiquidProbeResult", "TryLiquidProbeCommandType", + # evotip seal command bundle + "EvotipSealPipette", + "EvotipSealPipetteParams", + "EvotipSealPipetteCreate", + "EvotipSealPipetteResult", + "EvotipSealPipetteCommandType", + # evotip unseal command bundle + "EvotipUnsealPipette", + "EvotipUnsealPipetteParams", + "EvotipUnsealPipetteCreate", + "EvotipUnsealPipetteResult", + "EvotipUnsealPipetteCommandType", + # evotip dispense command bundle + "EvotipDispense", + "EvotipDispenseParams", + "EvotipDispenseCreate", + "EvotipDispenseResult", + "EvotipDispenseCommandType", ] diff --git a/api/src/opentrons/protocol_engine/commands/absorbance_reader/close_lid.py b/api/src/opentrons/protocol_engine/commands/absorbance_reader/close_lid.py index 41c1e65bce9..fd6e279d659 100644 --- a/api/src/opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +++ b/api/src/opentrons/protocol_engine/commands/absorbance_reader/close_lid.py @@ -132,7 +132,7 @@ class CloseLid(BaseCommand[CloseLidParams, CloseLidResult, ErrorOccurrence]): commandType: CloseLidCommandType = "absorbanceReader/closeLid" params: CloseLidParams - result: Optional[CloseLidResult] + result: Optional[CloseLidResult] = None _ImplementationCls: Type[CloseLidImpl] = CloseLidImpl diff --git a/api/src/opentrons/protocol_engine/commands/absorbance_reader/initialize.py b/api/src/opentrons/protocol_engine/commands/absorbance_reader/initialize.py index bcb2639d0a5..5fa810455ec 100644 --- a/api/src/opentrons/protocol_engine/commands/absorbance_reader/initialize.py +++ b/api/src/opentrons/protocol_engine/commands/absorbance_reader/initialize.py @@ -137,7 +137,7 @@ class Initialize(BaseCommand[InitializeParams, InitializeResult, ErrorOccurrence commandType: InitializeCommandType = "absorbanceReader/initialize" params: InitializeParams - result: Optional[InitializeResult] + result: Optional[InitializeResult] = None _ImplementationCls: Type[InitializeImpl] = InitializeImpl diff --git a/api/src/opentrons/protocol_engine/commands/absorbance_reader/open_lid.py b/api/src/opentrons/protocol_engine/commands/absorbance_reader/open_lid.py index 96495a2bcde..3fa965e33b3 100644 --- a/api/src/opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +++ b/api/src/opentrons/protocol_engine/commands/absorbance_reader/open_lid.py @@ -133,7 +133,7 @@ class OpenLid(BaseCommand[OpenLidParams, OpenLidResult, ErrorOccurrence]): commandType: OpenLidCommandType = "absorbanceReader/openLid" params: OpenLidParams - result: Optional[OpenLidResult] + result: Optional[OpenLidResult] = None _ImplementationCls: Type[OpenLidImpl] = OpenLidImpl diff --git a/api/src/opentrons/protocol_engine/commands/absorbance_reader/read.py b/api/src/opentrons/protocol_engine/commands/absorbance_reader/read.py index c8f7dca8706..a4a3aa58a5e 100644 --- a/api/src/opentrons/protocol_engine/commands/absorbance_reader/read.py +++ b/api/src/opentrons/protocol_engine/commands/absorbance_reader/read.py @@ -182,6 +182,9 @@ async def execute( # noqa: C901 ) file_ids.append(file_id) + state_update.files_added = update_types.FilesAddedUpdate( + file_ids=file_ids + ) # Return success data to api return SuccessData( public=ReadAbsorbanceResult( @@ -209,7 +212,7 @@ class ReadAbsorbance( commandType: ReadAbsorbanceCommandType = "absorbanceReader/read" params: ReadAbsorbanceParams - result: Optional[ReadAbsorbanceResult] + result: Optional[ReadAbsorbanceResult] = None _ImplementationCls: Type[ReadAbsorbanceImpl] = ReadAbsorbanceImpl diff --git a/api/src/opentrons/protocol_engine/commands/air_gap_in_place.py b/api/src/opentrons/protocol_engine/commands/air_gap_in_place.py index bf6bbafc3d5..df38886b0cc 100644 --- a/api/src/opentrons/protocol_engine/commands/air_gap_in_place.py +++ b/api/src/opentrons/protocol_engine/commands/air_gap_in_place.py @@ -148,7 +148,7 @@ class AirGapInPlace( commandType: AirGapInPlaceCommandType = "airGapInPlace" params: AirGapInPlaceParams - result: Optional[AirGapInPlaceResult] + result: Optional[AirGapInPlaceResult] = None _ImplementationCls: Type[AirGapInPlaceImplementation] = AirGapInPlaceImplementation diff --git a/api/src/opentrons/protocol_engine/commands/command_unions.py b/api/src/opentrons/protocol_engine/commands/command_unions.py index a69c3ef5e79..917cd3e6fbb 100644 --- a/api/src/opentrons/protocol_engine/commands/command_unions.py +++ b/api/src/opentrons/protocol_engine/commands/command_unions.py @@ -377,6 +377,30 @@ TryLiquidProbeCommandType, ) +from .evotip_seal_pipette import ( + EvotipSealPipette, + EvotipSealPipetteParams, + EvotipSealPipetteCreate, + EvotipSealPipetteResult, + EvotipSealPipetteCommandType, +) + +from .evotip_dispense import ( + EvotipDispense, + EvotipDispenseParams, + EvotipDispenseCreate, + EvotipDispenseResult, + EvotipDispenseCommandType, +) + +from .evotip_unseal_pipette import ( + EvotipUnsealPipette, + EvotipUnsealPipetteParams, + EvotipUnsealPipetteCreate, + EvotipUnsealPipetteResult, + EvotipUnsealPipetteCommandType, +) + Command = Annotated[ Union[ AirGapInPlace, @@ -423,6 +447,9 @@ GetNextTip, LiquidProbe, TryLiquidProbe, + EvotipSealPipette, + EvotipDispense, + EvotipUnsealPipette, heater_shaker.WaitForTemperature, heater_shaker.SetTargetTemperature, heater_shaker.DeactivateHeater, @@ -516,6 +543,9 @@ GetNextTipParams, LiquidProbeParams, TryLiquidProbeParams, + EvotipSealPipetteParams, + EvotipDispenseParams, + EvotipUnsealPipetteParams, heater_shaker.WaitForTemperatureParams, heater_shaker.SetTargetTemperatureParams, heater_shaker.DeactivateHeaterParams, @@ -607,6 +637,9 @@ GetNextTipCommandType, LiquidProbeCommandType, TryLiquidProbeCommandType, + EvotipSealPipetteCommandType, + EvotipDispenseCommandType, + EvotipUnsealPipetteCommandType, heater_shaker.WaitForTemperatureCommandType, heater_shaker.SetTargetTemperatureCommandType, heater_shaker.DeactivateHeaterCommandType, @@ -699,6 +732,9 @@ GetNextTipCreate, LiquidProbeCreate, TryLiquidProbeCreate, + EvotipSealPipetteCreate, + EvotipDispenseCreate, + EvotipUnsealPipetteCreate, heater_shaker.WaitForTemperatureCreate, heater_shaker.SetTargetTemperatureCreate, heater_shaker.DeactivateHeaterCreate, @@ -799,6 +835,9 @@ GetNextTipResult, LiquidProbeResult, TryLiquidProbeResult, + EvotipSealPipetteResult, + EvotipDispenseResult, + EvotipUnsealPipetteResult, heater_shaker.WaitForTemperatureResult, heater_shaker.SetTargetTemperatureResult, heater_shaker.DeactivateHeaterResult, diff --git a/api/src/opentrons/protocol_engine/commands/evotip_dispense.py b/api/src/opentrons/protocol_engine/commands/evotip_dispense.py new file mode 100644 index 00000000000..b028d72fc45 --- /dev/null +++ b/api/src/opentrons/protocol_engine/commands/evotip_dispense.py @@ -0,0 +1,158 @@ +"""Evotip Dispense-in-place command request, result, and implementation models.""" + +from __future__ import annotations +from typing import TYPE_CHECKING, Optional, Type, Union +from typing_extensions import Literal + +from opentrons.protocol_engine.errors import UnsupportedLabwareForActionError +from .pipetting_common import ( + PipetteIdMixin, + FlowRateMixin, + DispenseVolumeMixin, + BaseLiquidHandlingResult, + dispense_in_place, + DEFAULT_CORRECTION_VOLUME, +) +from .movement_common import ( + LiquidHandlingWellLocationMixin, + StallOrCollisionError, + move_to_well, +) + +from .command import ( + AbstractCommandImpl, + BaseCommand, + BaseCommandCreate, + SuccessData, + DefinedErrorData, +) +from ..state.update_types import StateUpdate +from ..resources import labware_validation +from ..errors import ProtocolEngineError + +if TYPE_CHECKING: + from ..execution import PipettingHandler, GantryMover, MovementHandler + from ..resources import ModelUtils + from ..state.state import StateView + + +EvotipDispenseCommandType = Literal["evotipDispense"] + + +class EvotipDispenseParams( + PipetteIdMixin, DispenseVolumeMixin, FlowRateMixin, LiquidHandlingWellLocationMixin +): + """Payload required to dispense in place.""" + + pass + + +class EvotipDispenseResult(BaseLiquidHandlingResult): + """Result data from the execution of a DispenseInPlace command.""" + + pass + + +_ExecuteReturn = Union[ + SuccessData[EvotipDispenseResult], + DefinedErrorData[StallOrCollisionError], +] + + +class EvotipDispenseImplementation( + AbstractCommandImpl[EvotipDispenseParams, _ExecuteReturn] +): + """DispenseInPlace command implementation.""" + + def __init__( + self, + pipetting: PipettingHandler, + state_view: StateView, + gantry_mover: GantryMover, + model_utils: ModelUtils, + movement: MovementHandler, + **kwargs: object, + ) -> None: + self._pipetting = pipetting + self._state_view = state_view + self._gantry_mover = gantry_mover + self._model_utils = model_utils + self._movement = movement + + async def execute(self, params: EvotipDispenseParams) -> _ExecuteReturn: + """Move to and dispense to the requested well.""" + well_location = params.wellLocation + labware_id = params.labwareId + well_name = params.wellName + + labware_definition = self._state_view.labware.get_definition(params.labwareId) + if not labware_validation.is_evotips(labware_definition.parameters.loadName): + raise UnsupportedLabwareForActionError( + f"Cannot use command: `EvotipDispense` with labware: {labware_definition.parameters.loadName}" + ) + move_result = await move_to_well( + movement=self._movement, + model_utils=self._model_utils, + pipette_id=params.pipetteId, + labware_id=labware_id, + well_name=well_name, + well_location=well_location, + ) + if isinstance(move_result, DefinedErrorData): + return move_result + + current_position = await self._gantry_mover.get_position(params.pipetteId) + result = await dispense_in_place( + pipette_id=params.pipetteId, + volume=params.volume, + flow_rate=params.flowRate, + push_out=None, + location_if_error={ + "retryLocation": ( + current_position.x, + current_position.y, + current_position.z, + ) + }, + pipetting=self._pipetting, + model_utils=self._model_utils, + correction_volume=params.correctionVolume or DEFAULT_CORRECTION_VOLUME, + ) + if isinstance(result, DefinedErrorData): + # TODO (chb, 2025-01-29): Remove this and the OverpressureError returns once disabled for this function + raise ProtocolEngineError( + message="Overpressure Error during Resin Tip Dispense Command." + ) + return SuccessData( + public=EvotipDispenseResult(volume=result.public.volume), + state_update=StateUpdate.reduce( + move_result.state_update, result.state_update + ), + ) + + +class EvotipDispense( + BaseCommand[ + EvotipDispenseParams, + EvotipDispenseResult, + StallOrCollisionError, + ] +): + """DispenseInPlace command model.""" + + commandType: EvotipDispenseCommandType = "evotipDispense" + params: EvotipDispenseParams + result: Optional[EvotipDispenseResult] = None + + _ImplementationCls: Type[ + EvotipDispenseImplementation + ] = EvotipDispenseImplementation + + +class EvotipDispenseCreate(BaseCommandCreate[EvotipDispenseParams]): + """DispenseInPlace command request model.""" + + commandType: EvotipDispenseCommandType = "evotipDispense" + params: EvotipDispenseParams + + _CommandCls: Type[EvotipDispense] = EvotipDispense diff --git a/api/src/opentrons/protocol_engine/commands/evotip_seal_pipette.py b/api/src/opentrons/protocol_engine/commands/evotip_seal_pipette.py new file mode 100644 index 00000000000..0e67e8fc2c0 --- /dev/null +++ b/api/src/opentrons/protocol_engine/commands/evotip_seal_pipette.py @@ -0,0 +1,331 @@ +"""Seal evotip resin tip command request, result, and implementation models.""" + +from __future__ import annotations +from pydantic import Field, BaseModel +from typing import TYPE_CHECKING, Optional, Type, Union +from opentrons.types import MountType +from opentrons.protocol_engine.types import MotorAxis +from typing_extensions import Literal + +from opentrons.protocol_engine.errors import UnsupportedLabwareForActionError +from ..resources import ModelUtils, labware_validation +from ..types import PickUpTipWellLocation, FluidKind, AspiratedFluid +from .pipetting_common import ( + PipetteIdMixin, +) +from .movement_common import ( + DestinationPositionResult, + StallOrCollisionError, + move_to_well, +) +from .command import ( + AbstractCommandImpl, + BaseCommand, + BaseCommandCreate, + DefinedErrorData, + SuccessData, +) + +from opentrons.hardware_control import HardwareControlAPI +from opentrons.hardware_control.types import Axis +from ..state.update_types import StateUpdate + +if TYPE_CHECKING: + from ..state.state import StateView + from ..execution import ( + MovementHandler, + TipHandler, + GantryMover, + PipettingHandler, + ) + + +EvotipSealPipetteCommandType = Literal["evotipSealPipette"] +_PREP_DISTANCE_DEFAULT = 8.25 +_PRESS_DISTANCE_DEFAULT = 3.5 +_EJECTOR_PUSH_MM_DEFAULT = 7.0 + + +class TipPickUpParams(BaseModel): + """Payload used to specify press-tip parameters for a seal command.""" + + prepDistance: float = Field( + default=0, description="The distance to move down to fit the tips on." + ) + pressDistance: float = Field( + default=0, description="The distance to press on tips." + ) + ejectorPushMm: float = Field( + default=0, + description="The distance to back off to ensure that the tip presence sensors are not triggered.", + ) + + +class EvotipSealPipetteParams(PipetteIdMixin): + """Payload needed to seal resin tips to a pipette.""" + + labwareId: str = Field(..., description="Identifier of labware to use.") + wellName: str = Field(..., description="Name of well to use in labware.") + wellLocation: PickUpTipWellLocation = Field( + default_factory=PickUpTipWellLocation, + description="Relative well location at which to pick up the tip.", + ) + tipPickUpParams: Optional[TipPickUpParams] = Field( + default=None, description="Specific parameters for " + ) + + +class EvotipSealPipetteResult(DestinationPositionResult): + """Result data from the execution of a EvotipSealPipette.""" + + tipVolume: float = Field( + 0, + description="Maximum volume of liquid that the picked up tip can hold, in µL.", + ge=0, + ) + + tipLength: float = Field( + 0, + description="The length of the tip in mm.", + ge=0, + ) + + tipDiameter: float = Field( + 0, + description="The diameter of the tip in mm.", + ge=0, + ) + + +_ExecuteReturn = Union[ + SuccessData[EvotipSealPipetteResult], + DefinedErrorData[StallOrCollisionError], +] + + +class EvotipSealPipetteImplementation( + AbstractCommandImpl[EvotipSealPipetteParams, _ExecuteReturn] +): + """Evotip seal pipette command implementation.""" + + def __init__( + self, + state_view: StateView, + tip_handler: TipHandler, + model_utils: ModelUtils, + movement: MovementHandler, + hardware_api: HardwareControlAPI, + gantry_mover: GantryMover, + pipetting: PipettingHandler, + **kwargs: object, + ) -> None: + self._state_view = state_view + self._tip_handler = tip_handler + self._model_utils = model_utils + self._movement = movement + self._gantry_mover = gantry_mover + self._pipetting = pipetting + self._hardware_api = hardware_api + + async def relative_pickup_tip( + self, + tip_pick_up_params: TipPickUpParams, + mount: MountType, + ) -> None: + """A relative press-fit pick up command using gantry moves.""" + prep_distance = tip_pick_up_params.prepDistance + press_distance = tip_pick_up_params.pressDistance + retract_distance = -1 * (prep_distance + press_distance) + + mount_axis = MotorAxis.LEFT_Z if mount == MountType.LEFT else MotorAxis.RIGHT_Z + + # TODO chb, 2025-01-29): Factor out the movement constants and relocate this logic into the hardware controller + await self._gantry_mover.move_axes( + axis_map={mount_axis: prep_distance}, speed=10, relative_move=True + ) + + # Drive mount down for press-fit + await self._gantry_mover.move_axes( + axis_map={mount_axis: press_distance}, + speed=10.0, + relative_move=True, + expect_stalls=True, + ) + # retract cam : 11.05 + await self._gantry_mover.move_axes( + axis_map={mount_axis: retract_distance}, speed=5.5, relative_move=True + ) + + async def cam_action_relative_pickup_tip( + self, + tip_pick_up_params: TipPickUpParams, + mount: MountType, + ) -> None: + """A cam action pick up command using gantry moves.""" + prep_distance = tip_pick_up_params.prepDistance + press_distance = tip_pick_up_params.pressDistance + ejector_push_mm = tip_pick_up_params.ejectorPushMm + retract_distance = -1 * (prep_distance + press_distance) + + mount_axis = MotorAxis.LEFT_Z if mount == MountType.LEFT else MotorAxis.RIGHT_Z + + # TODO chb, 2025-01-29): Factor out the movement constants and relocate this logic into the hardware controller + await self._gantry_mover.move_axes( + axis_map={mount_axis: -6}, speed=10, relative_move=True + ) + + # Drive Q down 3mm at fast speed - look into the pick up tip fuinction to find slow and fast: 10.0 + await self._gantry_mover.move_axes( + axis_map={MotorAxis.AXIS_96_CHANNEL_CAM: prep_distance}, + speed=10.0, + relative_move=True, + ) + # 2.8mm at slow speed - cam action pickup speed: 5.5 + await self._gantry_mover.move_axes( + axis_map={MotorAxis.AXIS_96_CHANNEL_CAM: press_distance}, + speed=5.5, + relative_move=True, + ) + # retract cam : 11.05 + await self._gantry_mover.move_axes( + axis_map={MotorAxis.AXIS_96_CHANNEL_CAM: retract_distance}, + speed=5.5, + relative_move=True, + ) + + # Lower tip presence + await self._gantry_mover.move_axes( + axis_map={mount_axis: 2}, speed=10, relative_move=True + ) + await self._gantry_mover.move_axes( + axis_map={MotorAxis.AXIS_96_CHANNEL_CAM: ejector_push_mm}, + speed=5.5, + relative_move=True, + ) + await self._gantry_mover.move_axes( + axis_map={MotorAxis.AXIS_96_CHANNEL_CAM: -1 * ejector_push_mm}, + speed=5.5, + relative_move=True, + ) + + async def execute( + self, params: EvotipSealPipetteParams + ) -> Union[SuccessData[EvotipSealPipetteResult], _ExecuteReturn]: + """Move to and pick up a tip using the requested pipette.""" + pipette_id = params.pipetteId + labware_id = params.labwareId + well_name = params.wellName + + labware_definition = self._state_view.labware.get_definition(params.labwareId) + if not labware_validation.is_evotips(labware_definition.parameters.loadName): + raise UnsupportedLabwareForActionError( + f"Cannot use command: `EvotipSealPipette` with labware: {labware_definition.parameters.loadName}" + ) + + well_location = self._state_view.geometry.convert_pick_up_tip_well_location( + well_location=params.wellLocation + ) + move_result = await move_to_well( + movement=self._movement, + model_utils=self._model_utils, + pipette_id=pipette_id, + labware_id=labware_id, + well_name=well_name, + well_location=well_location, + ) + if isinstance(move_result, DefinedErrorData): + return move_result + + # Aspirate to move plunger to a maximum volume position per pipette type + tip_geometry = self._state_view.geometry.get_nominal_tip_geometry( + pipette_id, labware_id, well_name + ) + maximum_volume = self._state_view.pipettes.get_maximum_volume(pipette_id) + if self._state_view.pipettes.get_mount(pipette_id) == MountType.LEFT: + await self._hardware_api.home(axes=[Axis.P_L]) + else: + await self._hardware_api.home(axes=[Axis.P_R]) + + # Begin relative pickup steps for the resin tips + + channels = self._state_view.tips.get_pipette_active_channels(pipette_id) + mount = self._state_view.pipettes.get_mount(pipette_id) + tip_pick_up_params = params.tipPickUpParams + if tip_pick_up_params is None: + tip_pick_up_params = TipPickUpParams( + prepDistance=_PREP_DISTANCE_DEFAULT, + pressDistance=_PRESS_DISTANCE_DEFAULT, + ejectorPushMm=_EJECTOR_PUSH_MM_DEFAULT, + ) + + if channels != 96: + await self.relative_pickup_tip( + tip_pick_up_params=tip_pick_up_params, + mount=mount, + ) + elif channels == 96: + await self.cam_action_relative_pickup_tip( + tip_pick_up_params=tip_pick_up_params, + mount=mount, + ) + else: + tip_geometry = await self._tip_handler.pick_up_tip( + pipette_id=pipette_id, + labware_id=labware_id, + well_name=well_name, + do_not_ignore_tip_presence=True, + ) + + # cache_tip + if self._state_view.config.use_virtual_pipettes is False: + self._tip_handler.cache_tip(pipette_id, tip_geometry) + hw_instr = self._hardware_api.hardware_instruments[mount.to_hw_mount()] + if hw_instr is not None: + hw_instr.set_current_volume(maximum_volume) + + state_update = StateUpdate() + state_update.update_pipette_tip_state( + pipette_id=pipette_id, + tip_geometry=tip_geometry, + ) + + state_update.set_fluid_aspirated( + pipette_id=pipette_id, + fluid=AspiratedFluid(kind=FluidKind.LIQUID, volume=maximum_volume), + ) + return SuccessData( + public=EvotipSealPipetteResult( + tipVolume=tip_geometry.volume, + tipLength=tip_geometry.length, + tipDiameter=tip_geometry.diameter, + position=move_result.public.position, + ), + state_update=state_update, + ) + + +class EvotipSealPipette( + BaseCommand[ + EvotipSealPipetteParams, + EvotipSealPipetteResult, + StallOrCollisionError, + ] +): + """Seal evotip resin tip command model.""" + + commandType: EvotipSealPipetteCommandType = "evotipSealPipette" + params: EvotipSealPipetteParams + result: Optional[EvotipSealPipetteResult] = None + + _ImplementationCls: Type[ + EvotipSealPipetteImplementation + ] = EvotipSealPipetteImplementation + + +class EvotipSealPipetteCreate(BaseCommandCreate[EvotipSealPipetteParams]): + """Seal evotip resin tip command creation request model.""" + + commandType: EvotipSealPipetteCommandType = "evotipSealPipette" + params: EvotipSealPipetteParams + + _CommandCls: Type[EvotipSealPipette] = EvotipSealPipette diff --git a/api/src/opentrons/protocol_engine/commands/evotip_unseal_pipette.py b/api/src/opentrons/protocol_engine/commands/evotip_unseal_pipette.py new file mode 100644 index 00000000000..e8cde34fd5c --- /dev/null +++ b/api/src/opentrons/protocol_engine/commands/evotip_unseal_pipette.py @@ -0,0 +1,160 @@ +"""Unseal evotip resin tip command request, result, and implementation models.""" + +from __future__ import annotations + +from pydantic import Field +from typing import TYPE_CHECKING, Optional, Type +from typing_extensions import Literal + +from opentrons.protocol_engine.resources.model_utils import ModelUtils +from opentrons.protocol_engine.errors import UnsupportedLabwareForActionError +from opentrons.protocol_engine.types import MotorAxis +from opentrons.types import MountType + +from ..types import DropTipWellLocation +from .pipetting_common import ( + PipetteIdMixin, +) +from .movement_common import ( + DestinationPositionResult, + move_to_well, + StallOrCollisionError, +) +from .command import ( + AbstractCommandImpl, + BaseCommand, + BaseCommandCreate, + DefinedErrorData, + SuccessData, +) +from ..resources import labware_validation + +if TYPE_CHECKING: + from ..state.state import StateView + from ..execution import MovementHandler, TipHandler, GantryMover + + +EvotipUnsealPipetteCommandType = Literal["evotipUnsealPipette"] + + +class EvotipUnsealPipetteParams(PipetteIdMixin): + """Payload required to drop a tip in a specific well.""" + + labwareId: str = Field(..., description="Identifier of labware to use.") + wellName: str = Field(..., description="Name of well to use in labware.") + wellLocation: DropTipWellLocation = Field( + default_factory=DropTipWellLocation, + description="Relative well location at which to drop the tip.", + ) + + +class EvotipUnsealPipetteResult(DestinationPositionResult): + """Result data from the execution of a DropTip command.""" + + pass + + +_ExecuteReturn = ( + SuccessData[EvotipUnsealPipetteResult] | DefinedErrorData[StallOrCollisionError] +) + + +class EvotipUnsealPipetteImplementation( + AbstractCommandImpl[EvotipUnsealPipetteParams, _ExecuteReturn] +): + """Drop tip command implementation.""" + + def __init__( + self, + state_view: StateView, + tip_handler: TipHandler, + movement: MovementHandler, + model_utils: ModelUtils, + gantry_mover: GantryMover, + **kwargs: object, + ) -> None: + self._state_view = state_view + self._tip_handler = tip_handler + self._movement_handler = movement + self._model_utils = model_utils + self._gantry_mover = gantry_mover + + async def execute(self, params: EvotipUnsealPipetteParams) -> _ExecuteReturn: + """Move to and drop a tip using the requested pipette.""" + pipette_id = params.pipetteId + labware_id = params.labwareId + well_name = params.wellName + + well_location = params.wellLocation + labware_definition = self._state_view.labware.get_definition(params.labwareId) + if not labware_validation.is_evotips(labware_definition.parameters.loadName): + raise UnsupportedLabwareForActionError( + f"Cannot use command: `EvotipUnsealPipette` with labware: {labware_definition.parameters.loadName}" + ) + is_partially_configured = self._state_view.pipettes.get_is_partially_configured( + pipette_id=pipette_id + ) + tip_drop_location = self._state_view.geometry.get_checked_tip_drop_location( + pipette_id=pipette_id, + labware_id=labware_id, + well_location=well_location, + partially_configured=is_partially_configured, + ) + + move_result = await move_to_well( + movement=self._movement_handler, + model_utils=self._model_utils, + pipette_id=pipette_id, + labware_id=labware_id, + well_name=well_name, + well_location=tip_drop_location, + ) + if isinstance(move_result, DefinedErrorData): + return move_result + + # Move to an appropriate position + mount = self._state_view.pipettes.get_mount(pipette_id) + + mount_axis = MotorAxis.LEFT_Z if mount == MountType.LEFT else MotorAxis.RIGHT_Z + await self._gantry_mover.move_axes( + axis_map={mount_axis: -14}, speed=10, relative_move=True + ) + + await self._tip_handler.drop_tip( + pipette_id=pipette_id, + home_after=None, + do_not_ignore_tip_presence=False, + ignore_plunger=True, + ) + + return SuccessData( + public=EvotipUnsealPipetteResult(position=move_result.public.position), + state_update=move_result.state_update.set_fluid_unknown( + pipette_id=pipette_id + ).update_pipette_tip_state(pipette_id=params.pipetteId, tip_geometry=None), + ) + + +class EvotipUnsealPipette( + BaseCommand[ + EvotipUnsealPipetteParams, EvotipUnsealPipetteResult, StallOrCollisionError + ] +): + """Evotip unseal command model.""" + + commandType: EvotipUnsealPipetteCommandType = "evotipUnsealPipette" + params: EvotipUnsealPipetteParams + result: Optional[EvotipUnsealPipetteResult] = None + + _ImplementationCls: Type[ + EvotipUnsealPipetteImplementation + ] = EvotipUnsealPipetteImplementation + + +class EvotipUnsealPipetteCreate(BaseCommandCreate[EvotipUnsealPipetteParams]): + """Evotip unseal command creation request model.""" + + commandType: EvotipUnsealPipetteCommandType = "evotipUnsealPipette" + params: EvotipUnsealPipetteParams + + _CommandCls: Type[EvotipUnsealPipette] = EvotipUnsealPipette diff --git a/api/src/opentrons/protocol_engine/commands/flex_stacker/configure.py b/api/src/opentrons/protocol_engine/commands/flex_stacker/configure.py index 85c0808b60a..d9af9a24f9c 100644 --- a/api/src/opentrons/protocol_engine/commands/flex_stacker/configure.py +++ b/api/src/opentrons/protocol_engine/commands/flex_stacker/configure.py @@ -62,7 +62,7 @@ class Configure(BaseCommand[ConfigureParams, ConfigureResult, ErrorOccurrence]): commandType: ConfigureCommandType = "flexStacker/configure" params: ConfigureParams - result: Optional[ConfigureResult] + result: Optional[ConfigureResult] = None _ImplementationCls: Type[ConfigureImpl] = ConfigureImpl diff --git a/api/src/opentrons/protocol_engine/commands/flex_stacker/retrieve.py b/api/src/opentrons/protocol_engine/commands/flex_stacker/retrieve.py index 7029b5772c3..2b723304017 100644 --- a/api/src/opentrons/protocol_engine/commands/flex_stacker/retrieve.py +++ b/api/src/opentrons/protocol_engine/commands/flex_stacker/retrieve.py @@ -113,7 +113,7 @@ class Retrieve(BaseCommand[RetrieveParams, RetrieveResult, ErrorOccurrence]): commandType: RetrieveCommandType = "flexStacker/retrieve" params: RetrieveParams - result: Optional[RetrieveResult] + result: Optional[RetrieveResult] = None _ImplementationCls: Type[RetrieveImpl] = RetrieveImpl diff --git a/api/src/opentrons/protocol_engine/commands/flex_stacker/store.py b/api/src/opentrons/protocol_engine/commands/flex_stacker/store.py index 37f2d9f7616..c2ef3e67f3e 100644 --- a/api/src/opentrons/protocol_engine/commands/flex_stacker/store.py +++ b/api/src/opentrons/protocol_engine/commands/flex_stacker/store.py @@ -100,7 +100,7 @@ class Store(BaseCommand[StoreParams, StoreResult, ErrorOccurrence]): commandType: StoreCommandType = "flexStacker/store" params: StoreParams - result: Optional[StoreResult] + result: Optional[StoreResult] = None _ImplementationCls: Type[StoreImpl] = StoreImpl diff --git a/api/src/opentrons/protocol_engine/commands/get_next_tip.py b/api/src/opentrons/protocol_engine/commands/get_next_tip.py index f9f2cb8ba61..9e0cf3b50cf 100644 --- a/api/src/opentrons/protocol_engine/commands/get_next_tip.py +++ b/api/src/opentrons/protocol_engine/commands/get_next_tip.py @@ -120,7 +120,7 @@ class GetNextTip(BaseCommand[GetNextTipParams, GetNextTipResult, ErrorOccurrence commandType: GetNextTipCommandType = "getNextTip" params: GetNextTipParams - result: Optional[GetNextTipResult] + result: Optional[GetNextTipResult] = None _ImplementationCls: Type[GetNextTipImplementation] = GetNextTipImplementation diff --git a/api/src/opentrons/protocol_engine/commands/liquid_probe.py b/api/src/opentrons/protocol_engine/commands/liquid_probe.py index a0418d53c9a..53cc3f77abd 100644 --- a/api/src/opentrons/protocol_engine/commands/liquid_probe.py +++ b/api/src/opentrons/protocol_engine/commands/liquid_probe.py @@ -19,12 +19,14 @@ from opentrons_shared_data.errors.exceptions import ( PipetteLiquidNotFoundError, UnsupportedHardwareCommand, + PipetteOverpressureError, ) from ..types import DeckPoint from .pipetting_common import ( LiquidNotFoundError, PipetteIdMixin, + OverpressureError, ) from .movement_common import ( WellLocationMixin, @@ -43,7 +45,7 @@ from ..errors.error_occurrence import ErrorOccurrence if TYPE_CHECKING: - from ..execution import MovementHandler, PipettingHandler + from ..execution import MovementHandler, PipettingHandler, GantryMover from ..resources import ModelUtils from ..state.state import StateView @@ -99,10 +101,14 @@ class TryLiquidProbeResult(DestinationPositionResult): _LiquidProbeExecuteReturn = Union[ SuccessData[LiquidProbeResult], - DefinedErrorData[LiquidNotFoundError] | DefinedErrorData[StallOrCollisionError], + DefinedErrorData[LiquidNotFoundError] + | DefinedErrorData[StallOrCollisionError] + | DefinedErrorData[OverpressureError], ] _TryLiquidProbeExecuteReturn = ( - SuccessData[TryLiquidProbeResult] | DefinedErrorData[StallOrCollisionError] + SuccessData[TryLiquidProbeResult] + | DefinedErrorData[StallOrCollisionError] + | DefinedErrorData[OverpressureError] ) @@ -110,19 +116,22 @@ class _ExecuteCommonResult(NamedTuple): # If the probe succeeded, the z_pos that it returned. # Or, if the probe found no liquid, the error representing that, # so calling code can propagate those details up. - z_pos_or_error: float | PipetteLiquidNotFoundError + z_pos_or_error: float | PipetteLiquidNotFoundError | PipetteOverpressureError state_update: update_types.StateUpdate deck_point: DeckPoint -async def _execute_common( +async def _execute_common( # noqa: C901 state_view: StateView, movement: MovementHandler, + gantry_mover: GantryMover, pipetting: PipettingHandler, model_utils: ModelUtils, params: _CommonParams, -) -> _ExecuteCommonResult | DefinedErrorData[StallOrCollisionError]: +) -> _ExecuteCommonResult | DefinedErrorData[StallOrCollisionError] | DefinedErrorData[ + OverpressureError +]: pipette_id = params.pipetteId labware_id = params.labwareId well_name = params.wellName @@ -173,6 +182,7 @@ async def _execute_common( if isinstance(move_result, DefinedErrorData): return move_result try: + current_position = await gantry_mover.get_position(params.pipetteId) z_pos = await pipetting.liquid_probe_in_place( pipette_id=pipette_id, labware_id=labware_id, @@ -185,6 +195,33 @@ async def _execute_common( state_update=move_result.state_update, deck_point=move_result.public.position, ) + except PipetteOverpressureError as e: + return DefinedErrorData( + public=OverpressureError( + id=model_utils.generate_id(), + createdAt=model_utils.get_timestamp(), + wrappedErrors=[ + ErrorOccurrence.from_failed( + id=model_utils.generate_id(), + createdAt=model_utils.get_timestamp(), + error=e, + ) + ], + errorInfo=( + { + # This is here bc its not optional in the type but we are not using the retry location for this case + "retryLocation": ( + current_position.x, + current_position.y, + current_position.z, + ) + } + ), + ), + state_update=move_result.state_update.set_fluid_unknown( + pipette_id=pipette_id + ), + ) else: return _ExecuteCommonResult( z_pos_or_error=z_pos, @@ -202,12 +239,14 @@ def __init__( self, state_view: StateView, movement: MovementHandler, + gantry_mover: GantryMover, pipetting: PipettingHandler, model_utils: ModelUtils, **kwargs: object, ) -> None: self._state_view = state_view self._movement = movement + self._gantry_mover = gantry_mover self._pipetting = pipetting self._model_utils = model_utils @@ -230,6 +269,7 @@ async def execute(self, params: _CommonParams) -> _LiquidProbeExecuteReturn: result = await _execute_common( state_view=self._state_view, movement=self._movement, + gantry_mover=self._gantry_mover, pipetting=self._pipetting, model_utils=self._model_utils, params=params, @@ -237,7 +277,9 @@ async def execute(self, params: _CommonParams) -> _LiquidProbeExecuteReturn: if isinstance(result, DefinedErrorData): return result z_pos_or_error, state_update, deck_point = result - if isinstance(z_pos_or_error, PipetteLiquidNotFoundError): + if isinstance( + z_pos_or_error, (PipetteLiquidNotFoundError, PipetteOverpressureError) + ): state_update.set_liquid_probed( labware_id=params.labwareId, well_name=params.wellName, @@ -294,12 +336,14 @@ def __init__( self, state_view: StateView, movement: MovementHandler, + gantry_mover: GantryMover, pipetting: PipettingHandler, model_utils: ModelUtils, **kwargs: object, ) -> None: self._state_view = state_view self._movement = movement + self._gantry_mover = gantry_mover self._pipetting = pipetting self._model_utils = model_utils @@ -313,6 +357,7 @@ async def execute(self, params: _CommonParams) -> _TryLiquidProbeExecuteReturn: result = await _execute_common( state_view=self._state_view, movement=self._movement, + gantry_mover=self._gantry_mover, pipetting=self._pipetting, model_utils=self._model_utils, params=params, @@ -321,7 +366,9 @@ async def execute(self, params: _CommonParams) -> _TryLiquidProbeExecuteReturn: return result z_pos_or_error, state_update, deck_point = result - if isinstance(z_pos_or_error, PipetteLiquidNotFoundError): + if isinstance( + z_pos_or_error, (PipetteLiquidNotFoundError, PipetteOverpressureError) + ): z_pos = None well_volume: float | update_types.ClearType = update_types.CLEAR else: @@ -354,26 +401,30 @@ class LiquidProbe( BaseCommand[ LiquidProbeParams, LiquidProbeResult, - LiquidNotFoundError | StallOrCollisionError, + LiquidNotFoundError | StallOrCollisionError | OverpressureError, ] ): """The model for a full `liquidProbe` command.""" commandType: LiquidProbeCommandType = "liquidProbe" params: LiquidProbeParams - result: Optional[LiquidProbeResult] + result: Optional[LiquidProbeResult] = None _ImplementationCls: Type[LiquidProbeImplementation] = LiquidProbeImplementation class TryLiquidProbe( - BaseCommand[TryLiquidProbeParams, TryLiquidProbeResult, StallOrCollisionError] + BaseCommand[ + TryLiquidProbeParams, + TryLiquidProbeResult, + StallOrCollisionError | OverpressureError, + ] ): """The model for a full `tryLiquidProbe` command.""" commandType: TryLiquidProbeCommandType = "tryLiquidProbe" params: TryLiquidProbeParams - result: Optional[TryLiquidProbeResult] + result: Optional[TryLiquidProbeResult] = None _ImplementationCls: Type[ TryLiquidProbeImplementation diff --git a/api/src/opentrons/protocol_engine/commands/load_labware.py b/api/src/opentrons/protocol_engine/commands/load_labware.py index f0d9f11b947..981ca04a11e 100644 --- a/api/src/opentrons/protocol_engine/commands/load_labware.py +++ b/api/src/opentrons/protocol_engine/commands/load_labware.py @@ -226,6 +226,11 @@ async def execute( # noqa: C901 module_id=params.location.moduleId, labware_id=loaded_labware.labware_id, ) + + self._state_view.labware.raise_if_labware_cannot_be_ondeck( + location=params.location, labware_definition=loaded_labware.definition + ) + return SuccessData( public=LoadLabwareResult( labwareId=loaded_labware.labware_id, diff --git a/api/src/opentrons/protocol_engine/commands/load_lid.py b/api/src/opentrons/protocol_engine/commands/load_lid.py index 323b1ab4271..529ee5b0e03 100644 --- a/api/src/opentrons/protocol_engine/commands/load_lid.py +++ b/api/src/opentrons/protocol_engine/commands/load_lid.py @@ -132,7 +132,7 @@ class LoadLid(BaseCommand[LoadLidParams, LoadLidResult, ErrorOccurrence]): commandType: LoadLidCommandType = "loadLid" params: LoadLidParams - result: Optional[LoadLidResult] + result: Optional[LoadLidResult] = None _ImplementationCls: Type[LoadLidImplementation] = LoadLidImplementation diff --git a/api/src/opentrons/protocol_engine/commands/load_lid_stack.py b/api/src/opentrons/protocol_engine/commands/load_lid_stack.py index c4aebebdf28..b879ec11084 100644 --- a/api/src/opentrons/protocol_engine/commands/load_lid_stack.py +++ b/api/src/opentrons/protocol_engine/commands/load_lid_stack.py @@ -206,7 +206,7 @@ class LoadLidStack( commandType: LoadLidStackCommandType = "loadLidStack" params: LoadLidStackParams - result: Optional[LoadLidStackResult] + result: Optional[LoadLidStackResult] = None _ImplementationCls: Type[LoadLidStackImplementation] = LoadLidStackImplementation diff --git a/api/src/opentrons/protocol_engine/commands/load_liquid_class.py b/api/src/opentrons/protocol_engine/commands/load_liquid_class.py index 8cb3d4a06fb..2dfcb089414 100644 --- a/api/src/opentrons/protocol_engine/commands/load_liquid_class.py +++ b/api/src/opentrons/protocol_engine/commands/load_liquid_class.py @@ -128,7 +128,7 @@ class LoadLiquidClass( commandType: LoadLiquidClassCommandType = "loadLiquidClass" params: LoadLiquidClassParams - result: Optional[LoadLiquidClassResult] + result: Optional[LoadLiquidClassResult] = None _ImplementationCls: Type[ LoadLiquidClassImplementation diff --git a/api/src/opentrons/protocol_engine/commands/move_labware.py b/api/src/opentrons/protocol_engine/commands/move_labware.py index afbc830ea66..6b10fc1ec8d 100644 --- a/api/src/opentrons/protocol_engine/commands/move_labware.py +++ b/api/src/opentrons/protocol_engine/commands/move_labware.py @@ -223,6 +223,15 @@ async def execute(self, params: MoveLabwareParams) -> _ExecuteReturn: # noqa: C self._state_view.labware.raise_if_labware_has_labware_on_top( labware_id=params.labwareId ) + + if isinstance(available_new_location, DeckSlotLocation): + self._state_view.labware.raise_if_labware_cannot_be_ondeck( + location=available_new_location, + labware_definition=self._state_view.labware.get_definition( + params.labwareId + ), + ) + if isinstance(available_new_location, OnLabwareLocation): self._state_view.labware.raise_if_labware_has_labware_on_top( available_new_location.labwareId diff --git a/api/src/opentrons/protocol_engine/commands/robot/close_gripper_jaw.py b/api/src/opentrons/protocol_engine/commands/robot/close_gripper_jaw.py index 36b027c351a..5ff11891a1b 100644 --- a/api/src/opentrons/protocol_engine/commands/robot/close_gripper_jaw.py +++ b/api/src/opentrons/protocol_engine/commands/robot/close_gripper_jaw.py @@ -70,7 +70,7 @@ class closeGripperJaw( commandType: closeGripperJawCommandType = "robot/closeGripperJaw" params: closeGripperJawParams - result: Optional[closeGripperJawResult] + result: Optional[closeGripperJawResult] = None _ImplementationCls: Type[ closeGripperJawImplementation diff --git a/api/src/opentrons/protocol_engine/commands/robot/move_axes_relative.py b/api/src/opentrons/protocol_engine/commands/robot/move_axes_relative.py index 99b30e9595a..c334e4017ce 100644 --- a/api/src/opentrons/protocol_engine/commands/robot/move_axes_relative.py +++ b/api/src/opentrons/protocol_engine/commands/robot/move_axes_relative.py @@ -85,7 +85,7 @@ class MoveAxesRelative( commandType: MoveAxesRelativeCommandType = "robot/moveAxesRelative" params: MoveAxesRelativeParams - result: Optional[MoveAxesRelativeResult] + result: Optional[MoveAxesRelativeResult] = None _ImplementationCls: Type[ MoveAxesRelativeImplementation diff --git a/api/src/opentrons/protocol_engine/commands/robot/move_axes_to.py b/api/src/opentrons/protocol_engine/commands/robot/move_axes_to.py index 93fc2746c84..81c4462af57 100644 --- a/api/src/opentrons/protocol_engine/commands/robot/move_axes_to.py +++ b/api/src/opentrons/protocol_engine/commands/robot/move_axes_to.py @@ -86,7 +86,7 @@ class MoveAxesTo(BaseCommand[MoveAxesToParams, MoveAxesToResult, ErrorOccurrence commandType: MoveAxesToCommandType = "robot/moveAxesTo" params: MoveAxesToParams - result: Optional[MoveAxesToResult] + result: Optional[MoveAxesToResult] = None _ImplementationCls: Type[MoveAxesToImplementation] = MoveAxesToImplementation diff --git a/api/src/opentrons/protocol_engine/commands/robot/move_to.py b/api/src/opentrons/protocol_engine/commands/robot/move_to.py index e2a3af07767..e0b5365c048 100644 --- a/api/src/opentrons/protocol_engine/commands/robot/move_to.py +++ b/api/src/opentrons/protocol_engine/commands/robot/move_to.py @@ -80,7 +80,7 @@ class MoveTo(BaseCommand[MoveToParams, MoveToResult, ErrorOccurrence]): commandType: MoveToCommandType = "robot/moveTo" params: MoveToParams - result: Optional[MoveToResult] + result: Optional[MoveToResult] = None _ImplementationCls: Type[MoveToImplementation] = MoveToImplementation diff --git a/api/src/opentrons/protocol_engine/commands/robot/open_gripper_jaw.py b/api/src/opentrons/protocol_engine/commands/robot/open_gripper_jaw.py index 22aa1debd42..83b58647394 100644 --- a/api/src/opentrons/protocol_engine/commands/robot/open_gripper_jaw.py +++ b/api/src/opentrons/protocol_engine/commands/robot/open_gripper_jaw.py @@ -61,7 +61,7 @@ class openGripperJaw( commandType: openGripperJawCommandType = "robot/openGripperJaw" params: openGripperJawParams - result: Optional[openGripperJawResult] + result: Optional[openGripperJawResult] = None _ImplementationCls: Type[ openGripperJawImplementation diff --git a/api/src/opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py b/api/src/opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py index 40f87af7772..ec294d5965c 100644 --- a/api/src/opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +++ b/api/src/opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py @@ -157,7 +157,7 @@ class RunExtendedProfile( commandType: RunExtendedProfileCommandType = "thermocycler/runExtendedProfile" params: RunExtendedProfileParams - result: Optional[RunExtendedProfileResult] + result: Optional[RunExtendedProfileResult] = None _ImplementationCls: Type[RunExtendedProfileImpl] = RunExtendedProfileImpl diff --git a/api/src/opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py b/api/src/opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py index 4c767625782..bd48c3c1c8b 100644 --- a/api/src/opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +++ b/api/src/opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py @@ -82,7 +82,7 @@ class UnsafeBlowOutInPlace( commandType: UnsafeBlowOutInPlaceCommandType = "unsafe/blowOutInPlace" params: UnsafeBlowOutInPlaceParams - result: Optional[UnsafeBlowOutInPlaceResult] + result: Optional[UnsafeBlowOutInPlaceResult] = None _ImplementationCls: Type[ UnsafeBlowOutInPlaceImplementation diff --git a/api/src/opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py b/api/src/opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py index 56a87a468dd..d6b0652a4c0 100644 --- a/api/src/opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +++ b/api/src/opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py @@ -99,7 +99,7 @@ class UnsafeDropTipInPlace( commandType: UnsafeDropTipInPlaceCommandType = "unsafe/dropTipInPlace" params: UnsafeDropTipInPlaceParams - result: Optional[UnsafeDropTipInPlaceResult] + result: Optional[UnsafeDropTipInPlaceResult] = None _ImplementationCls: Type[ UnsafeDropTipInPlaceImplementation diff --git a/api/src/opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py b/api/src/opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py index 4f80db24f42..c38bc1ed481 100644 --- a/api/src/opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +++ b/api/src/opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py @@ -66,7 +66,7 @@ class UnsafeEngageAxes( commandType: UnsafeEngageAxesCommandType = "unsafe/engageAxes" params: UnsafeEngageAxesParams - result: Optional[UnsafeEngageAxesResult] + result: Optional[UnsafeEngageAxesResult] = None _ImplementationCls: Type[ UnsafeEngageAxesImplementation diff --git a/api/src/opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py b/api/src/opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py index c69cea29243..cd105867524 100644 --- a/api/src/opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +++ b/api/src/opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py @@ -192,7 +192,7 @@ class UnsafePlaceLabware( commandType: UnsafePlaceLabwareCommandType = "unsafe/placeLabware" params: UnsafePlaceLabwareParams - result: Optional[UnsafePlaceLabwareResult] + result: Optional[UnsafePlaceLabwareResult] = None _ImplementationCls: Type[ UnsafePlaceLabwareImplementation diff --git a/api/src/opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py b/api/src/opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py index 6f8f5b71fce..dd7248a1932 100644 --- a/api/src/opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +++ b/api/src/opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py @@ -61,7 +61,7 @@ class UnsafeUngripLabware( commandType: UnsafeUngripLabwareCommandType = "unsafe/ungripLabware" params: UnsafeUngripLabwareParams - result: Optional[UnsafeUngripLabwareResult] + result: Optional[UnsafeUngripLabwareResult] = None _ImplementationCls: Type[ UnsafeUngripLabwareImplementation diff --git a/api/src/opentrons/protocol_engine/commands/unsafe/update_position_estimators.py b/api/src/opentrons/protocol_engine/commands/unsafe/update_position_estimators.py index 6b050d6472f..0f6e4c5d7eb 100644 --- a/api/src/opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +++ b/api/src/opentrons/protocol_engine/commands/unsafe/update_position_estimators.py @@ -74,7 +74,7 @@ class UpdatePositionEstimators( commandType: UpdatePositionEstimatorsCommandType = "unsafe/updatePositionEstimators" params: UpdatePositionEstimatorsParams - result: Optional[UpdatePositionEstimatorsResult] + result: Optional[UpdatePositionEstimatorsResult] = None _ImplementationCls: Type[ UpdatePositionEstimatorsImplementation diff --git a/api/src/opentrons/protocol_engine/errors/__init__.py b/api/src/opentrons/protocol_engine/errors/__init__.py index 85d89e8e2fb..1bd68359e74 100644 --- a/api/src/opentrons/protocol_engine/errors/__init__.py +++ b/api/src/opentrons/protocol_engine/errors/__init__.py @@ -11,6 +11,7 @@ PickUpTipTipNotAttachedError, TipAttachedError, CommandDoesNotExistError, + UnsupportedLabwareForActionError, LabwareNotLoadedError, LabwareNotLoadedOnModuleError, LabwareNotLoadedOnLabwareError, @@ -18,6 +19,7 @@ LiquidDoesNotExistError, LabwareDefinitionDoesNotExistError, LabwareCannotBeStackedError, + LabwareCannotSitOnDeckError, LabwareIsInStackError, LabwareOffsetDoesNotExistError, LabwareIsNotTipRackError, @@ -104,8 +106,10 @@ "LabwareNotLoadedOnLabwareError", "LabwareNotOnDeckError", "LiquidDoesNotExistError", + "UnsupportedLabwareForActionError", "LabwareDefinitionDoesNotExistError", "LabwareCannotBeStackedError", + "LabwareCannotSitOnDeckError", "LabwareIsInStackError", "LabwareOffsetDoesNotExistError", "LabwareIsNotTipRackError", diff --git a/api/src/opentrons/protocol_engine/errors/exceptions.py b/api/src/opentrons/protocol_engine/errors/exceptions.py index 3aa7c0562ab..614b8aec639 100644 --- a/api/src/opentrons/protocol_engine/errors/exceptions.py +++ b/api/src/opentrons/protocol_engine/errors/exceptions.py @@ -283,6 +283,19 @@ def __init__( super().__init__(ErrorCodes.GENERAL_ERROR, message, details, wrapping) +class LabwareCannotSitOnDeckError(ProtocolEngineError): + """Raised when a labware is incompatible with a deck slot.""" + + def __init__( + self, + message: Optional[str] = None, + details: Optional[Dict[str, Any]] = None, + wrapping: Optional[Sequence[EnumeratedError]] = None, + ) -> None: + """Build a LabwareCannotSitOnDeckError.""" + super().__init__(ErrorCodes.GENERAL_ERROR, message, details, wrapping) + + class LabwareIsInStackError(ProtocolEngineError): """Raised when trying to move to or physically interact with a labware that has another labware on top.""" @@ -374,6 +387,19 @@ def __init__( super().__init__(ErrorCodes.GENERAL_ERROR, message, details, wrapping) +class UnsupportedLabwareForActionError(ProtocolEngineError): + """Raised when trying to use an unsupported labware for a command.""" + + def __init__( + self, + message: Optional[str] = None, + details: Optional[Dict[str, Any]] = None, + wrapping: Optional[Sequence[EnumeratedError]] = None, + ) -> None: + """Build a UnsupportedLabwareForActionError.""" + super().__init__(ErrorCodes.GENERAL_ERROR, message, details, wrapping) + + class WellDoesNotExistError(ProtocolEngineError): """Raised when referencing a well that does not exist.""" diff --git a/api/src/opentrons/protocol_engine/execution/gantry_mover.py b/api/src/opentrons/protocol_engine/execution/gantry_mover.py index 5413de8741c..ca90d0a12cb 100644 --- a/api/src/opentrons/protocol_engine/execution/gantry_mover.py +++ b/api/src/opentrons/protocol_engine/execution/gantry_mover.py @@ -114,6 +114,7 @@ async def move_axes( critical_point: Optional[Dict[MotorAxis, float]] = None, speed: Optional[float] = None, relative_move: bool = False, + expect_stalls: bool = False, ) -> Dict[MotorAxis, float]: """Move a set of axes a given distance.""" ... @@ -341,6 +342,7 @@ async def move_axes( critical_point: Optional[Dict[MotorAxis, float]] = None, speed: Optional[float] = None, relative_move: bool = False, + expect_stalls: bool = False, ) -> Dict[MotorAxis, float]: """Move a set of axes a given distance. @@ -349,6 +351,7 @@ async def move_axes( critical_point: A critical point override for axes speed: Optional speed parameter for the move. relative_move: Whether the axis map needs to be converted from a relative to absolute move. + expect_stalls: Whether it is expected that the move triggers a stall error. """ try: pos_hw = self._convert_axis_map_for_hw(axis_map) @@ -385,6 +388,7 @@ async def move_axes( await self._hardware_api.move_axes( position=absolute_pos, speed=speed, + expect_stalls=expect_stalls, ) except PositionUnknownError as e: @@ -588,6 +592,7 @@ async def move_axes( critical_point: Optional[Dict[MotorAxis, float]] = None, speed: Optional[float] = None, relative_move: bool = False, + expect_stalls: bool = False, ) -> Dict[MotorAxis, float]: """Move the give axes map. No-op in virtual implementation.""" mount = self.pick_mount_from_axis_map(axis_map) diff --git a/api/src/opentrons/protocol_engine/execution/hardware_stopper.py b/api/src/opentrons/protocol_engine/execution/hardware_stopper.py index 81d4f10d94d..0312f622ac9 100644 --- a/api/src/opentrons/protocol_engine/execution/hardware_stopper.py +++ b/api/src/opentrons/protocol_engine/execution/hardware_stopper.py @@ -65,7 +65,7 @@ async def _home_everything_except_plungers(self) -> None: axes=[MotorAxis.X, MotorAxis.Y, MotorAxis.LEFT_Z, MotorAxis.RIGHT_Z] ) - async def _drop_tip(self) -> None: + async def _try_to_drop_tips(self) -> None: """Drop currently attached tip, if any, into trash after a run cancel.""" attached_tips = self._state_store.pipettes.get_all_attached_tips() @@ -134,9 +134,9 @@ async def do_stop_and_recover( PostRunHardwareState.HOME_THEN_DISENGAGE, ) if drop_tips_after_run: - await self._drop_tip() - await self._hardware_api.stop(home_after=home_after_stop) - else: - await self._hardware_api.stop(home_after=False) - if home_after_stop: - await self._home_everything_except_plungers() + await self._try_to_drop_tips() + + await self._hardware_api.stop(home_after=False) + + if home_after_stop: + await self._home_everything_except_plungers() diff --git a/api/src/opentrons/protocol_engine/execution/tip_handler.py b/api/src/opentrons/protocol_engine/execution/tip_handler.py index 8a58536c10b..d27925e00fe 100644 --- a/api/src/opentrons/protocol_engine/execution/tip_handler.py +++ b/api/src/opentrons/protocol_engine/execution/tip_handler.py @@ -62,6 +62,7 @@ async def pick_up_tip( pipette_id: str, labware_id: str, well_name: str, + do_not_ignore_tip_presence: bool = True, ) -> TipGeometry: """Pick up the named tip. @@ -75,7 +76,13 @@ async def pick_up_tip( """ ... - async def drop_tip(self, pipette_id: str, home_after: Optional[bool]) -> None: + async def drop_tip( + self, + pipette_id: str, + home_after: Optional[bool], + do_not_ignore_tip_presence: bool = True, + ignore_plunger: bool = False, + ) -> None: """Drop the attached tip into the current location. Pipette should be in place over the destination prior to calling this method. @@ -230,6 +237,7 @@ async def pick_up_tip( pipette_id: str, labware_id: str, well_name: str, + do_not_ignore_tip_presence: bool = True, ) -> TipGeometry: """See documentation on abstract base class.""" hw_mount = self._get_hw_mount(pipette_id) @@ -253,10 +261,11 @@ async def pick_up_tip( await self._hardware_api.tip_pickup_moves( mount=hw_mount, presses=None, increment=None ) - try: - await self.verify_tip_presence(pipette_id, TipPresenceStatus.PRESENT) - except TipNotAttachedError as e: - raise PickUpTipTipNotAttachedError(tip_geometry=tip_geometry) from e + if do_not_ignore_tip_presence: + try: + await self.verify_tip_presence(pipette_id, TipPresenceStatus.PRESENT) + except TipNotAttachedError as e: + raise PickUpTipTipNotAttachedError(tip_geometry=tip_geometry) from e self.cache_tip(pipette_id, tip_geometry) @@ -264,7 +273,13 @@ async def pick_up_tip( return tip_geometry - async def drop_tip(self, pipette_id: str, home_after: Optional[bool]) -> None: + async def drop_tip( + self, + pipette_id: str, + home_after: Optional[bool], + do_not_ignore_tip_presence: bool = True, + ignore_plunger: bool = False, + ) -> None: """See documentation on abstract base class.""" hw_mount = self._get_hw_mount(pipette_id) @@ -275,10 +290,13 @@ async def drop_tip(self, pipette_id: str, home_after: Optional[bool]) -> None: else: kwargs = {} - await self._hardware_api.tip_drop_moves(mount=hw_mount, **kwargs) + await self._hardware_api.tip_drop_moves( + mount=hw_mount, ignore_plunger=ignore_plunger, **kwargs + ) - # Allow TipNotAttachedError to propagate. - await self.verify_tip_presence(pipette_id, TipPresenceStatus.ABSENT) + if do_not_ignore_tip_presence: + # Allow TipNotAttachedError to propagate. + await self.verify_tip_presence(pipette_id, TipPresenceStatus.ABSENT) self.remove_tip(pipette_id) @@ -383,6 +401,7 @@ async def pick_up_tip( pipette_id: str, labware_id: str, well_name: str, + do_not_ignore_tip_presence: bool = True, ) -> TipGeometry: """Pick up a tip at the current location using a virtual pipette. @@ -424,6 +443,8 @@ async def drop_tip( self, pipette_id: str, home_after: Optional[bool], + do_not_ignore_tip_presence: bool = True, + ignore_plunger: bool = False, ) -> None: """Pick up a tip at the current location using a virtual pipette. diff --git a/api/src/opentrons/protocol_engine/resources/labware_validation.py b/api/src/opentrons/protocol_engine/resources/labware_validation.py index 17ee211cb66..fb806e4d0b9 100644 --- a/api/src/opentrons/protocol_engine/resources/labware_validation.py +++ b/api/src/opentrons/protocol_engine/resources/labware_validation.py @@ -21,6 +21,11 @@ def is_lid_stack(load_name: str) -> bool: return load_name == "protocol_engine_lid_stack_object" +def is_evotips(load_name: str) -> bool: + """Check if a labware is an evotips tiprack.""" + return load_name == "evotips_opentrons_96_labware" + + def validate_definition_is_labware(definition: LabwareDefinition) -> bool: """Validate that one of the definition's allowed roles is `labware`. @@ -51,6 +56,14 @@ def validate_labware_can_be_stacked( return below_labware_load_name in top_labware_definition.stackingOffsetWithLabware +def validate_labware_can_be_ondeck(definition: LabwareDefinition) -> bool: + """Validate that the labware being loaded onto the deck can sit in a slot.""" + return ( + definition.parameters.quirks is None + or "stackingOnly" not in definition.parameters.quirks + ) + + def validate_gripper_compatible(definition: LabwareDefinition) -> bool: """Validate that the labware definition does not have a quirk disallowing movement with gripper.""" return ( diff --git a/api/src/opentrons/protocol_engine/state/commands.py b/api/src/opentrons/protocol_engine/state/commands.py index e059212e73f..dd8ec108687 100644 --- a/api/src/opentrons/protocol_engine/state/commands.py +++ b/api/src/opentrons/protocol_engine/state/commands.py @@ -1,4 +1,5 @@ """Protocol engine commands sub-state.""" + from __future__ import annotations import enum @@ -304,7 +305,7 @@ def _handle_queue_command_action(self, action: QueueCommandAction) -> None: # TODO(mc, 2021-06-22): mypy has trouble with this automatic # request > command mapping, figure out how to type precisely # (or wait for a future mypy version that can figure it out). - queued_command = action.request._CommandCls.model_construct( # type: ignore[call-arg] + queued_command = action.request._CommandCls.model_construct( id=action.command_id, key=( action.request.key @@ -506,7 +507,10 @@ def _handle_door_change_action(self, action: DoorChangeAction) -> None: pass case QueueStatus.RUNNING | QueueStatus.PAUSED: self._state.queue_status = QueueStatus.PAUSED - case QueueStatus.AWAITING_RECOVERY | QueueStatus.AWAITING_RECOVERY_PAUSED: + case ( + QueueStatus.AWAITING_RECOVERY + | QueueStatus.AWAITING_RECOVERY_PAUSED + ): self._state.queue_status = QueueStatus.AWAITING_RECOVERY_PAUSED elif action.door_state == DoorState.CLOSED: self._state.is_door_blocking = False diff --git a/api/src/opentrons/protocol_engine/state/labware.py b/api/src/opentrons/protocol_engine/state/labware.py index 6063a46e6b8..553538895e5 100644 --- a/api/src/opentrons/protocol_engine/state/labware.py +++ b/api/src/opentrons/protocol_engine/state/labware.py @@ -937,6 +937,19 @@ def raise_if_labware_in_location( f"Labware {labware.loadName} is already present at {location}." ) + def raise_if_labware_cannot_be_ondeck( + self, + location: LabwareLocation, + labware_definition: LabwareDefinition, + ) -> None: + """Raise an error if the labware cannot be in the specified location.""" + if isinstance( + location, (DeckSlotLocation, AddressableAreaLocation) + ) and not labware_validation.validate_labware_can_be_ondeck(labware_definition): + raise errors.LabwareCannotSitOnDeckError( + f"{labware_definition.parameters.loadName} cannot sit in a slot by itself." + ) + def raise_if_labware_incompatible_with_plate_reader( self, labware_definition: LabwareDefinition, diff --git a/api/src/opentrons/protocol_engine/state/pipettes.py b/api/src/opentrons/protocol_engine/state/pipettes.py index 9b7d289e890..fc7b1da20ac 100644 --- a/api/src/opentrons/protocol_engine/state/pipettes.py +++ b/api/src/opentrons/protocol_engine/state/pipettes.py @@ -331,6 +331,11 @@ def _update_volumes(self, state_update: update_types.StateUpdate) -> None: def _update_aspirated( self, update: update_types.PipetteAspiratedFluidUpdate ) -> None: + if self._state.pipette_contents_by_id[update.pipette_id] is None: + self._state.pipette_contents_by_id[ + update.pipette_id + ] = fluid_stack.FluidStack() + self._fluid_stack_log_if_empty(update.pipette_id).add_fluid(update.fluid) def _update_ejected(self, update: update_types.PipetteEjectedFluidUpdate) -> None: diff --git a/api/src/opentrons/protocols/labware.py b/api/src/opentrons/protocols/labware.py index d3159ee5d9f..ec05e3cbb72 100644 --- a/api/src/opentrons/protocols/labware.py +++ b/api/src/opentrons/protocols/labware.py @@ -4,7 +4,7 @@ import json import os from pathlib import Path -from typing import Any, AnyStr, Dict, Optional, Union, List +from typing import Any, AnyStr, Dict, Optional, Union, List, Sequence, Literal import jsonschema # type: ignore @@ -17,10 +17,30 @@ USER_DEFS_PATH, ) from opentrons_shared_data.labware.types import LabwareDefinition +from opentrons_shared_data.errors.exceptions import InvalidProtocolData MODULE_LOG = logging.getLogger(__name__) +LabwareProblem = Literal[ + "no-schema-id", "bad-schema-id", "schema-mismatch", "invalid-json" +] + + +class NotALabwareError(InvalidProtocolData): + def __init__( + self, problem: LabwareProblem, wrapping: Sequence[BaseException] + ) -> None: + messages: dict[LabwareProblem, str] = { + "no-schema-id": "No schema ID present in file", + "bad-schema-id": "Bad schema ID in file", + "invalid-json": "File does not contain valid JSON", + "schema-mismatch": "File does not match labware schema", + } + super().__init__( + message=messages[problem], detail={"kind": problem}, wrapping=wrapping + ) + def get_labware_definition( load_name: str, @@ -126,7 +146,7 @@ def save_definition( json.dump(labware_def, f) -def verify_definition( +def verify_definition( # noqa: C901 contents: Union[AnyStr, LabwareDefinition, Dict[str, Any]] ) -> LabwareDefinition: """Verify that an input string is a labware definition and return it. @@ -146,15 +166,24 @@ def verify_definition( if isinstance(contents, dict): to_return = contents else: - to_return = json.loads(contents) + try: + to_return = json.loads(contents) + except json.JSONDecodeError as e: + raise NotALabwareError("invalid-json", [e]) from e try: schema_version = to_return["schemaVersion"] + except KeyError as e: + raise NotALabwareError("no-schema-id", [e]) from e + + try: schema = schemata_by_version[schema_version] - except KeyError: - raise RuntimeError( - f'Invalid or unknown labware schema version {to_return.get("schemaVersion", None)}' - ) - jsonschema.validate(to_return, schema) + except KeyError as e: + raise NotALabwareError("bad-schema-id", [e]) from e + + try: + jsonschema.validate(to_return, schema) + except jsonschema.ValidationError as e: + raise NotALabwareError("schema-mismatch", [e]) from e # we can type ignore this because if it passes the jsonschema it has # the correct structure diff --git a/api/src/opentrons/util/entrypoint_util.py b/api/src/opentrons/util/entrypoint_util.py index 2da4cac874c..508f6769bc5 100644 --- a/api/src/opentrons/util/entrypoint_util.py +++ b/api/src/opentrons/util/entrypoint_util.py @@ -6,7 +6,6 @@ from dataclasses import dataclass import json import logging -from json import JSONDecodeError import pathlib import subprocess import sys @@ -21,8 +20,6 @@ TYPE_CHECKING, ) -from jsonschema import ValidationError # type: ignore - from opentrons.calibration_storage.deck_configuration import ( deserialize_deck_configuration, ) @@ -32,7 +29,7 @@ JUPYTER_NOTEBOOK_LABWARE_DIR, SystemArchitecture, ) -from opentrons.protocol_api import labware +from opentrons.protocols import labware from opentrons.calibration_storage import helpers from opentrons.protocol_engine.errors.error_occurrence import ( ErrorOccurrence as ProtocolEngineErrorOccurrence, @@ -79,7 +76,7 @@ def labware_from_paths( if child.is_file() and child.suffix.endswith("json"): try: defn = labware.verify_definition(child.read_bytes()) - except (ValidationError, JSONDecodeError): + except labware.NotALabwareError: log.info(f"{child}: invalid labware, ignoring") log.debug( f"{child}: labware invalid because of this exception.", diff --git a/api/tests/opentrons/hardware_control/test_ot3_api.py b/api/tests/opentrons/hardware_control/test_ot3_api.py index 200549108db..cbb5838c266 100644 --- a/api/tests/opentrons/hardware_control/test_ot3_api.py +++ b/api/tests/opentrons/hardware_control/test_ot3_api.py @@ -1895,7 +1895,9 @@ async def test_move_axes( await ot3_hardware.move_axes(position=input_position) mock_check_motor.return_value = True - mock_move.assert_called_once_with(target_position=expected_move_pos, speed=None) + mock_move.assert_called_once_with( + target_position=expected_move_pos, speed=None, expect_stalls=False + ) async def test_move_gripper_mount_without_gripper_attached( @@ -1913,14 +1915,14 @@ async def test_move_expect_stall_flag( expected = HWStopCondition.stall if expect_stalls else HWStopCondition.none - await ot3_hardware.move_to(Mount.LEFT, Point(0, 0, 0), _expect_stalls=expect_stalls) + await ot3_hardware.move_to(Mount.LEFT, Point(0, 0, 0), expect_stalls=expect_stalls) mock_backend_move.assert_called_once() _, _, _, condition = mock_backend_move.call_args_list[0][0] assert condition == expected mock_backend_move.reset_mock() await ot3_hardware.move_rel( - Mount.LEFT, Point(10, 0, 0), _expect_stalls=expect_stalls + Mount.LEFT, Point(10, 0, 0), expect_stalls=expect_stalls ) mock_backend_move.assert_called_once() _, _, _, condition = mock_backend_move.call_args_list[0][0] diff --git a/api/tests/opentrons/protocol_engine/commands/test_evotip_dispense.py b/api/tests/opentrons/protocol_engine/commands/test_evotip_dispense.py new file mode 100644 index 00000000000..abde82a1d77 --- /dev/null +++ b/api/tests/opentrons/protocol_engine/commands/test_evotip_dispense.py @@ -0,0 +1,137 @@ +"""Test evotip dispense in place commands.""" +import json + +import pytest +from decoy import Decoy + +from opentrons.protocol_engine import ( + LiquidHandlingWellLocation, + WellOrigin, + WellOffset, + DeckPoint, +) +from opentrons.types import Point +from opentrons.protocol_engine.execution import ( + PipettingHandler, + GantryMover, + MovementHandler, +) + +from opentrons_shared_data.labware.labware_definition import LabwareDefinition +from opentrons.protocol_engine.commands.command import SuccessData +from opentrons.protocol_engine.commands.evotip_dispense import ( + EvotipDispenseParams, + EvotipDispenseResult, + EvotipDispenseImplementation, +) +from opentrons.protocol_engine.resources import ModelUtils +from opentrons.protocol_engine.state.state import StateView +from opentrons.protocol_engine.state import update_types + +from opentrons_shared_data import load_shared_data + + +@pytest.fixture +def evotips_definition() -> LabwareDefinition: + """A fixturee of the evotips definition.""" + # TODO (chb 2025-01-29): When we migrate all labware to v3 we can clean this up + return LabwareDefinition.model_validate( + json.loads( + load_shared_data( + "labware/definitions/3/evotips_opentrons_96_labware/1.json" + ) + ) + ) + + +@pytest.fixture +def subject( + pipetting: PipettingHandler, + state_view: StateView, + gantry_mover: GantryMover, + model_utils: ModelUtils, + movement: MovementHandler, + **kwargs: object, +) -> EvotipDispenseImplementation: + """Build a command implementation.""" + return EvotipDispenseImplementation( + pipetting=pipetting, + state_view=state_view, + gantry_mover=gantry_mover, + model_utils=model_utils, + movement=movement, + ) + + +async def test_evotip_dispense_implementation( + decoy: Decoy, + movement: MovementHandler, + gantry_mover: GantryMover, + pipetting: PipettingHandler, + state_view: StateView, + subject: EvotipDispenseImplementation, + evotips_definition: LabwareDefinition, +) -> None: + """It should dispense in place.""" + well_location = LiquidHandlingWellLocation( + origin=WellOrigin.TOP, offset=WellOffset(x=0, y=0, z=0) + ) + + data = EvotipDispenseParams( + pipetteId="pipette-id-abc123", + labwareId="labware-id-abc123", + wellName="A3", + volume=100, + flowRate=456, + ) + + decoy.when( + await movement.move_to_well( + pipette_id="pipette-id-abc123", + labware_id="labware-id-abc123", + well_name="A3", + well_location=well_location, + current_well=None, + force_direct=False, + minimum_z_height=None, + speed=None, + operation_volume=None, + ) + ).then_return(Point(x=1, y=2, z=3)) + + decoy.when(state_view.labware.get_definition("labware-id-abc123")).then_return( + evotips_definition + ) + + decoy.when( + await pipetting.dispense_in_place( + pipette_id="pipette-id-abc123", + volume=100.0, + flow_rate=456.0, + push_out=None, + correction_volume=0, + ) + ).then_return(100) + + decoy.when(await gantry_mover.get_position("pipette-id-abc123")).then_return( + Point(1, 2, 3) + ) + + result = await subject.execute(data) + + assert result == SuccessData( + public=EvotipDispenseResult(volume=100), + state_update=update_types.StateUpdate( + pipette_location=update_types.PipetteLocationUpdate( + pipette_id="pipette-id-abc123", + new_location=update_types.Well( + labware_id="labware-id-abc123", + well_name="A3", + ), + new_deck_point=DeckPoint.model_construct(x=1, y=2, z=3), + ), + pipette_aspirated_fluid=update_types.PipetteEjectedFluidUpdate( + pipette_id="pipette-id-abc123", volume=100 + ), + ), + ) diff --git a/api/tests/opentrons/protocol_engine/commands/test_evotip_seal_pipette.py b/api/tests/opentrons/protocol_engine/commands/test_evotip_seal_pipette.py new file mode 100644 index 00000000000..0a2805913e6 --- /dev/null +++ b/api/tests/opentrons/protocol_engine/commands/test_evotip_seal_pipette.py @@ -0,0 +1,300 @@ +"""Test evotip seal commands.""" + +import pytest +from datetime import datetime + +from decoy import Decoy, matchers +from unittest.mock import sentinel + +from opentrons_shared_data.labware.labware_definition import LabwareDefinition + +from opentrons_shared_data.errors.exceptions import StallOrCollisionDetectedError + +from opentrons.types import MountType, Point + +from opentrons.protocol_engine import ( + WellLocation, + PickUpTipWellLocation, + WellOffset, + DeckPoint, +) +from opentrons.protocol_engine.errors import PickUpTipTipNotAttachedError +from opentrons.protocol_engine.execution import MovementHandler, GantryMover, TipHandler +from opentrons.protocol_engine.resources import ModelUtils +from opentrons.protocol_engine.state import update_types +from opentrons.protocol_engine.state.state import StateView +from opentrons.protocol_engine.types import TipGeometry, FluidKind, AspiratedFluid + +from opentrons.protocol_engine.commands.movement_common import StallOrCollisionError +from opentrons.protocol_engine.commands.command import DefinedErrorData, SuccessData +from opentrons.protocol_engine.commands.evotip_seal_pipette import ( + EvotipSealPipetteParams, + EvotipSealPipetteResult, + EvotipSealPipetteImplementation, +) +from opentrons.protocol_engine.execution import ( + PipettingHandler, +) +from opentrons.hardware_control import HardwareControlAPI +import json +from opentrons_shared_data import load_shared_data + + +@pytest.fixture +def evotips_definition() -> LabwareDefinition: + """A fixturee of the evotips definition.""" + # TODO (chb 2025-01-29): When we migrate all labware to v3 we can clean this up + return LabwareDefinition.model_validate( + json.loads( + load_shared_data( + "labware/definitions/3/evotips_opentrons_96_labware/1.json" + ) + ) + ) + + +async def test_success( + decoy: Decoy, + state_view: StateView, + movement: MovementHandler, + tip_handler: TipHandler, + model_utils: ModelUtils, + gantry_mover: GantryMover, + evotips_definition: LabwareDefinition, + hardware_api: HardwareControlAPI, + pipetting: PipettingHandler, +) -> None: + """A PickUpTip command should have an execution implementation.""" + subject = EvotipSealPipetteImplementation( + state_view=state_view, + movement=movement, + tip_handler=tip_handler, + model_utils=model_utils, + gantry_mover=gantry_mover, + hardware_api=hardware_api, + pipetting=pipetting, + ) + + decoy.when(state_view.pipettes.get_mount("pipette-id")).then_return(MountType.LEFT) + + decoy.when( + state_view.geometry.convert_pick_up_tip_well_location( + well_location=PickUpTipWellLocation(offset=WellOffset(x=1, y=2, z=3)) + ) + ).then_return(WellLocation(offset=WellOffset(x=1, y=2, z=3))) + + decoy.when(state_view.labware.get_definition("labware-id")).then_return( + evotips_definition + ) + decoy.when( + await movement.move_to_well( + pipette_id="pipette-id", + labware_id="labware-id", + well_name="A3", + well_location=WellLocation(offset=WellOffset(x=1, y=2, z=3)), + current_well=None, + force_direct=False, + minimum_z_height=None, + speed=None, + operation_volume=None, + ) + ).then_return(Point(x=111, y=222, z=333)) + decoy.when( + state_view.geometry.get_nominal_tip_geometry("pipette-id", "labware-id", "A3") + ).then_return(TipGeometry(length=42, diameter=5, volume=300)) + decoy.when(state_view.pipettes.get_maximum_volume("pipette-id")).then_return(1000) + + decoy.when( + await tip_handler.pick_up_tip( + pipette_id="pipette-id", + labware_id="labware-id", + well_name="A3", + ) + ).then_return(TipGeometry(length=42, diameter=5, volume=300)) + + result = await subject.execute( + EvotipSealPipetteParams( + pipetteId="pipette-id", + labwareId="labware-id", + wellName="A3", + wellLocation=PickUpTipWellLocation(offset=WellOffset(x=1, y=2, z=3)), + ) + ) + + assert result == SuccessData( + public=EvotipSealPipetteResult( + tipLength=42, + tipVolume=300, + tipDiameter=5, + position=DeckPoint(x=111, y=222, z=333), + ), + state_update=update_types.StateUpdate( + pipette_tip_state=update_types.PipetteTipStateUpdate( + pipette_id="pipette-id", + tip_geometry=TipGeometry(length=42, diameter=5, volume=300), + ), + pipette_aspirated_fluid=update_types.PipetteAspiratedFluidUpdate( + pipette_id="pipette-id", + fluid=AspiratedFluid(kind=FluidKind.LIQUID, volume=1000), + ), + ), + ) + + +async def test_no_tip_physically_missing_error( + decoy: Decoy, + state_view: StateView, + movement: MovementHandler, + tip_handler: TipHandler, + model_utils: ModelUtils, + gantry_mover: GantryMover, + hardware_api: HardwareControlAPI, + pipetting: PipettingHandler, + evotips_definition: LabwareDefinition, +) -> None: + """It should not return a TipPhysicallyMissingError even though evotips do not sit high enough on the pipette to be detected by the tip sensor.""" + subject = EvotipSealPipetteImplementation( + state_view=state_view, + movement=movement, + tip_handler=tip_handler, + model_utils=model_utils, + gantry_mover=gantry_mover, + hardware_api=hardware_api, + pipetting=pipetting, + ) + + pipette_id = "pipette-id" + labware_id = "labware-id" + well_name = "well-name" + error_id = "error-id" + error_created_at = datetime(1234, 5, 6) + + decoy.when( + state_view.geometry.convert_pick_up_tip_well_location( + well_location=PickUpTipWellLocation(offset=WellOffset()) + ) + ).then_return(WellLocation(offset=WellOffset())) + + decoy.when( + await movement.move_to_well( + pipette_id="pipette-id", + labware_id="labware-id", + well_name="well-name", + well_location=WellLocation(offset=WellOffset()), + current_well=None, + force_direct=False, + minimum_z_height=None, + speed=None, + operation_volume=None, + ) + ).then_return(Point(x=111, y=222, z=333)) + decoy.when( + state_view.geometry.get_nominal_tip_geometry(pipette_id, labware_id, well_name) + ).then_return(TipGeometry(length=42, diameter=5, volume=300)) + + decoy.when( + await tip_handler.pick_up_tip( + pipette_id=pipette_id, labware_id=labware_id, well_name=well_name + ) + ).then_raise(PickUpTipTipNotAttachedError(tip_geometry=sentinel.tip_geometry)) + decoy.when(model_utils.generate_id()).then_return(error_id) + decoy.when(model_utils.get_timestamp()).then_return(error_created_at) + decoy.when(state_view.labware.get_definition(labware_id)).then_return( + evotips_definition + ) + decoy.when(state_view.pipettes.get_maximum_volume(pipette_id)).then_return(1000) + + result = await subject.execute( + EvotipSealPipetteParams( + pipetteId=pipette_id, labwareId=labware_id, wellName=well_name + ) + ) + + assert result == SuccessData( + public=EvotipSealPipetteResult( + tipLength=42, + tipVolume=300, + tipDiameter=5, + position=DeckPoint(x=111, y=222, z=333), + ), + state_update=update_types.StateUpdate( + pipette_tip_state=update_types.PipetteTipStateUpdate( + pipette_id="pipette-id", + tip_geometry=TipGeometry(length=42, diameter=5, volume=300), + ), + pipette_aspirated_fluid=update_types.PipetteAspiratedFluidUpdate( + pipette_id="pipette-id", + fluid=AspiratedFluid(kind=FluidKind.LIQUID, volume=1000), + ), + ), + ) + + +async def test_stall_error( + decoy: Decoy, + state_view: StateView, + movement: MovementHandler, + tip_handler: TipHandler, + model_utils: ModelUtils, + gantry_mover: GantryMover, + hardware_api: HardwareControlAPI, + pipetting: PipettingHandler, + evotips_definition: LabwareDefinition, +) -> None: + """It should return a TipPhysicallyMissingError if the HW API indicates that.""" + subject = EvotipSealPipetteImplementation( + state_view=state_view, + movement=movement, + tip_handler=tip_handler, + model_utils=model_utils, + gantry_mover=gantry_mover, + hardware_api=hardware_api, + pipetting=pipetting, + ) + + pipette_id = "pipette-id" + labware_id = "labware-id" + well_name = "well-name" + error_id = "error-id" + error_created_at = datetime(1234, 5, 6) + + decoy.when( + state_view.geometry.convert_pick_up_tip_well_location( + well_location=PickUpTipWellLocation(offset=WellOffset()) + ) + ).then_return(WellLocation(offset=WellOffset())) + + decoy.when( + await movement.move_to_well( + pipette_id="pipette-id", + labware_id="labware-id", + well_name="well-name", + well_location=WellLocation(offset=WellOffset()), + current_well=None, + force_direct=False, + minimum_z_height=None, + speed=None, + operation_volume=None, + ) + ).then_raise(StallOrCollisionDetectedError()) + + decoy.when(model_utils.generate_id()).then_return(error_id) + decoy.when(model_utils.get_timestamp()).then_return(error_created_at) + decoy.when(state_view.labware.get_definition(labware_id)).then_return( + evotips_definition + ) + + result = await subject.execute( + EvotipSealPipetteParams( + pipetteId=pipette_id, labwareId=labware_id, wellName=well_name + ) + ) + + assert result == DefinedErrorData( + public=StallOrCollisionError.model_construct( + id=error_id, createdAt=error_created_at, wrappedErrors=[matchers.Anything()] + ), + state_update=update_types.StateUpdate( + pipette_location=update_types.CLEAR, + ), + ) diff --git a/api/tests/opentrons/protocol_engine/commands/test_evotip_unseal_pipette.py b/api/tests/opentrons/protocol_engine/commands/test_evotip_unseal_pipette.py new file mode 100644 index 00000000000..54c7e222bd2 --- /dev/null +++ b/api/tests/opentrons/protocol_engine/commands/test_evotip_unseal_pipette.py @@ -0,0 +1,330 @@ +"""Test evotip unseal commands.""" + +from datetime import datetime + +import pytest +from decoy import Decoy, matchers + +from opentrons_shared_data.errors.exceptions import StallOrCollisionDetectedError + +from opentrons.protocol_engine import ( + DropTipWellLocation, + DropTipWellOrigin, + WellLocation, + WellOffset, + DeckPoint, +) +from opentrons.protocol_engine.commands.command import DefinedErrorData, SuccessData +from opentrons.protocol_engine.commands.evotip_unseal_pipette import ( + EvotipUnsealPipetteParams, + EvotipUnsealPipetteResult, + EvotipUnsealPipetteImplementation, +) +from opentrons.protocol_engine.commands.movement_common import StallOrCollisionError +from opentrons.protocol_engine.errors.exceptions import TipAttachedError +from opentrons.protocol_engine.resources.model_utils import ModelUtils +from opentrons.protocol_engine.state import update_types +from opentrons.protocol_engine.state.state import StateView +from opentrons.protocol_engine.execution import MovementHandler, GantryMover, TipHandler +from opentrons_shared_data.labware.labware_definition import LabwareDefinition +import json +from opentrons_shared_data import load_shared_data + +from opentrons.types import Point + + +@pytest.fixture +def mock_state_view(decoy: Decoy) -> StateView: + """Get a mock StateView.""" + return decoy.mock(cls=StateView) + + +@pytest.fixture +def mock_movement_handler(decoy: Decoy) -> MovementHandler: + """Get a mock MovementHandler.""" + return decoy.mock(cls=MovementHandler) + + +@pytest.fixture +def mock_tip_handler(decoy: Decoy) -> TipHandler: + """Get a mock TipHandler.""" + return decoy.mock(cls=TipHandler) + + +@pytest.fixture +def mock_model_utils(decoy: Decoy) -> ModelUtils: + """Get a mock ModelUtils.""" + return decoy.mock(cls=ModelUtils) + + +def test_drop_tip_params_defaults() -> None: + """A drop tip should use a `WellOrigin.DROP_TIP` by default.""" + default_params = EvotipUnsealPipetteParams.model_validate( + {"pipetteId": "abc", "labwareId": "def", "wellName": "ghj"} + ) + + assert default_params.wellLocation == DropTipWellLocation( + origin=DropTipWellOrigin.DEFAULT, offset=WellOffset(x=0, y=0, z=0) + ) + + +def test_drop_tip_params_default_origin() -> None: + """A drop tip should drop a `WellOrigin.DROP_TIP` by default even if an offset is given.""" + default_params = EvotipUnsealPipetteParams.model_validate( + { + "pipetteId": "abc", + "labwareId": "def", + "wellName": "ghj", + "wellLocation": {"offset": {"x": 1, "y": 2, "z": 3}}, + } + ) + + assert default_params.wellLocation == DropTipWellLocation( + origin=DropTipWellOrigin.DEFAULT, offset=WellOffset(x=1, y=2, z=3) + ) + + +@pytest.fixture +def evotips_definition() -> LabwareDefinition: + """A fixturee of the evotips definition.""" + # TODO (chb 2025-01-29): When we migrate all labware to v3 we can clean this up + return LabwareDefinition.model_validate( + json.loads( + load_shared_data( + "labware/definitions/3/evotips_opentrons_96_labware/1.json" + ) + ) + ) + + +async def test_drop_tip_implementation( + decoy: Decoy, + mock_state_view: StateView, + mock_movement_handler: MovementHandler, + mock_tip_handler: TipHandler, + mock_model_utils: ModelUtils, + gantry_mover: GantryMover, + evotips_definition: LabwareDefinition, +) -> None: + """A DropTip command should have an execution implementation.""" + subject = EvotipUnsealPipetteImplementation( + state_view=mock_state_view, + movement=mock_movement_handler, + tip_handler=mock_tip_handler, + model_utils=mock_model_utils, + gantry_mover=gantry_mover, + ) + + params = EvotipUnsealPipetteParams( + pipetteId="abc", + labwareId="123", + wellName="A3", + wellLocation=DropTipWellLocation(offset=WellOffset(x=1, y=2, z=3)), + ) + decoy.when(mock_state_view.labware.get_definition("123")).then_return( + evotips_definition + ) + + decoy.when( + mock_state_view.pipettes.get_is_partially_configured(pipette_id="abc") + ).then_return(False) + + decoy.when( + mock_state_view.geometry.get_checked_tip_drop_location( + pipette_id="abc", + labware_id="123", + well_location=DropTipWellLocation(offset=WellOffset(x=1, y=2, z=3)), + partially_configured=False, + ) + ).then_return(WellLocation(offset=WellOffset(x=4, y=5, z=6))) + + decoy.when( + await mock_movement_handler.move_to_well( + pipette_id="abc", + labware_id="123", + well_name="A3", + well_location=WellLocation(offset=WellOffset(x=4, y=5, z=6)), + current_well=None, + force_direct=False, + minimum_z_height=None, + speed=None, + operation_volume=None, + ) + ).then_return(Point(x=111, y=222, z=333)) + + result = await subject.execute(params) + + assert result == SuccessData( + public=EvotipUnsealPipetteResult(position=DeckPoint(x=111, y=222, z=333)), + state_update=update_types.StateUpdate( + pipette_location=update_types.PipetteLocationUpdate( + pipette_id="abc", + new_location=update_types.Well( + labware_id="123", + well_name="A3", + ), + new_deck_point=DeckPoint(x=111, y=222, z=333), + ), + pipette_tip_state=update_types.PipetteTipStateUpdate( + pipette_id="abc", tip_geometry=None + ), + pipette_aspirated_fluid=update_types.PipetteUnknownFluidUpdate( + pipette_id="abc" + ), + ), + ) + decoy.verify( + await mock_tip_handler.drop_tip( + pipette_id="abc", + home_after=None, + do_not_ignore_tip_presence=False, + ignore_plunger=True, + ), + times=1, + ) + + +async def test_tip_attached_error( + decoy: Decoy, + mock_state_view: StateView, + mock_movement_handler: MovementHandler, + mock_tip_handler: TipHandler, + mock_model_utils: ModelUtils, + gantry_mover: GantryMover, + evotips_definition: LabwareDefinition, +) -> None: + """A Evotip Unseal command should have an execution implementation.""" + subject = EvotipUnsealPipetteImplementation( + state_view=mock_state_view, + movement=mock_movement_handler, + tip_handler=mock_tip_handler, + model_utils=mock_model_utils, + gantry_mover=gantry_mover, + ) + + params = EvotipUnsealPipetteParams( + pipetteId="abc", + labwareId="123", + wellName="A3", + wellLocation=DropTipWellLocation(offset=WellOffset(x=1, y=2, z=3)), + ) + decoy.when(mock_state_view.labware.get_definition("123")).then_return( + evotips_definition + ) + + decoy.when( + mock_state_view.pipettes.get_is_partially_configured(pipette_id="abc") + ).then_return(False) + + decoy.when( + mock_state_view.geometry.get_checked_tip_drop_location( + pipette_id="abc", + labware_id="123", + well_location=DropTipWellLocation(offset=WellOffset(x=1, y=2, z=3)), + partially_configured=False, + ) + ).then_return(WellLocation(offset=WellOffset(x=4, y=5, z=6))) + + decoy.when( + await mock_movement_handler.move_to_well( + pipette_id="abc", + labware_id="123", + well_name="A3", + well_location=WellLocation(offset=WellOffset(x=4, y=5, z=6)), + current_well=None, + force_direct=False, + minimum_z_height=None, + speed=None, + operation_volume=None, + ) + ).then_return(Point(x=111, y=222, z=333)) + decoy.when( + await mock_tip_handler.drop_tip( + pipette_id="abc", + home_after=None, + do_not_ignore_tip_presence=False, + ignore_plunger=True, + ) + ).then_raise(TipAttachedError("Egads!")) + + decoy.when(mock_model_utils.generate_id()).then_return("error-id") + decoy.when(mock_model_utils.get_timestamp()).then_return( + datetime(year=1, month=2, day=3) + ) + + with pytest.raises(TipAttachedError): + await subject.execute(params) + + +async def test_stall_error( + decoy: Decoy, + mock_state_view: StateView, + mock_movement_handler: MovementHandler, + mock_tip_handler: TipHandler, + mock_model_utils: ModelUtils, + gantry_mover: GantryMover, + evotips_definition: LabwareDefinition, +) -> None: + """A DropTip command should have an execution implementation.""" + subject = EvotipUnsealPipetteImplementation( + state_view=mock_state_view, + movement=mock_movement_handler, + tip_handler=mock_tip_handler, + model_utils=mock_model_utils, + gantry_mover=gantry_mover, + ) + + params = EvotipUnsealPipetteParams( + pipetteId="abc", + labwareId="123", + wellName="A3", + wellLocation=DropTipWellLocation(offset=WellOffset(x=1, y=2, z=3)), + ) + decoy.when(mock_state_view.labware.get_definition("123")).then_return( + evotips_definition + ) + + decoy.when( + mock_state_view.pipettes.get_is_partially_configured(pipette_id="abc") + ).then_return(False) + + decoy.when( + mock_state_view.geometry.get_checked_tip_drop_location( + pipette_id="abc", + labware_id="123", + well_location=DropTipWellLocation(offset=WellOffset(x=1, y=2, z=3)), + partially_configured=False, + ) + ).then_return(WellLocation(offset=WellOffset(x=4, y=5, z=6))) + + decoy.when( + await mock_movement_handler.move_to_well( + pipette_id="abc", + labware_id="123", + well_name="A3", + well_location=WellLocation(offset=WellOffset(x=4, y=5, z=6)), + current_well=None, + force_direct=False, + minimum_z_height=None, + speed=None, + operation_volume=None, + ) + ).then_raise(StallOrCollisionDetectedError()) + + decoy.when(mock_model_utils.generate_id()).then_return("error-id") + decoy.when(mock_model_utils.get_timestamp()).then_return( + datetime(year=1, month=2, day=3) + ) + + result = await subject.execute(params) + + assert result == DefinedErrorData( + public=StallOrCollisionError.model_construct( + id="error-id", + createdAt=datetime(year=1, month=2, day=3), + wrappedErrors=[matchers.Anything()], + ), + state_update=update_types.StateUpdate( + pipette_location=update_types.CLEAR, + ), + ) diff --git a/api/tests/opentrons/protocol_engine/commands/test_liquid_probe.py b/api/tests/opentrons/protocol_engine/commands/test_liquid_probe.py index c9661512aaa..14a269bf300 100644 --- a/api/tests/opentrons/protocol_engine/commands/test_liquid_probe.py +++ b/api/tests/opentrons/protocol_engine/commands/test_liquid_probe.py @@ -49,6 +49,7 @@ from opentrons.protocol_engine.execution import ( MovementHandler, PipettingHandler, + GantryMover, ) from opentrons.protocol_engine.resources.model_utils import ModelUtils @@ -106,6 +107,7 @@ def subject( implementation_type: EitherImplementationType, state_view: StateView, movement: MovementHandler, + gantry_mover: GantryMover, pipetting: PipettingHandler, model_utils: ModelUtils, ) -> Union[LiquidProbeImplementation, TryLiquidProbeImplementation]: @@ -114,6 +116,7 @@ def subject( state_view=state_view, pipetting=pipetting, movement=movement, + gantry_mover=gantry_mover, model_utils=model_utils, ) @@ -317,7 +320,6 @@ async def test_liquid_not_found_error( operation_volume=None, ), ).then_return(position) - decoy.when( await pipetting.liquid_probe_in_place( pipette_id=pipette_id, diff --git a/api/tests/opentrons/protocol_engine/execution/test_gantry_mover.py b/api/tests/opentrons/protocol_engine/execution/test_gantry_mover.py index 2c872c003d1..caa8d0cc3b6 100644 --- a/api/tests/opentrons/protocol_engine/execution/test_gantry_mover.py +++ b/api/tests/opentrons/protocol_engine/execution/test_gantry_mover.py @@ -568,7 +568,9 @@ def _current_position(mount: Mount, refresh: bool) -> Dict[HardwareAxis, float]: pos = await subject.move_axes(axis_map, critical_point, 100, relative_move) decoy.verify( - await ot3_hardware_api.move_axes(position=call_to_hw, speed=100), + await ot3_hardware_api.move_axes( + position=call_to_hw, speed=100, expect_stalls=False + ), times=1, ) assert pos == { diff --git a/api/tests/opentrons/protocol_engine/execution/test_hardware_stopper.py b/api/tests/opentrons/protocol_engine/execution/test_hardware_stopper.py index 503d681bced..c3a1e38d490 100644 --- a/api/tests/opentrons/protocol_engine/execution/test_hardware_stopper.py +++ b/api/tests/opentrons/protocol_engine/execution/test_hardware_stopper.py @@ -1,4 +1,5 @@ """Test hardware stopping execution and side effects.""" + from __future__ import annotations import pytest @@ -78,12 +79,12 @@ async def test_hardware_halt( @pytest.mark.parametrize( - argnames=["post_run_hardware_state", "expected_home_after"], - argvalues=[ - (PostRunHardwareState.STAY_ENGAGED_IN_PLACE, False), - (PostRunHardwareState.DISENGAGE_IN_PLACE, False), - (PostRunHardwareState.HOME_AND_STAY_ENGAGED, True), - (PostRunHardwareState.HOME_THEN_DISENGAGE, True), + "post_run_hardware_state", + [ + PostRunHardwareState.STAY_ENGAGED_IN_PLACE, + PostRunHardwareState.DISENGAGE_IN_PLACE, + PostRunHardwareState.HOME_AND_STAY_ENGAGED, + PostRunHardwareState.HOME_THEN_DISENGAGE, ], ) async def test_hardware_stopping_sequence( @@ -94,7 +95,6 @@ async def test_hardware_stopping_sequence( mock_tip_handler: TipHandler, subject: HardwareStopper, post_run_hardware_state: PostRunHardwareState, - expected_home_after: bool, ) -> None: """It should stop the hardware, and home the robot. Flex no longer performs automatic drop tip..""" decoy.when(state_store.pipettes.get_all_attached_tips()).then_return( @@ -113,7 +113,7 @@ async def test_hardware_stopping_sequence( await movement.home( axes=[MotorAxis.X, MotorAxis.Y, MotorAxis.LEFT_Z, MotorAxis.RIGHT_Z] ), - await hardware_api.stop(home_after=expected_home_after), + await hardware_api.stop(home_after=False), ) @@ -122,6 +122,7 @@ async def test_hardware_stopping_sequence_without_pipette_tips( hardware_api: HardwareAPI, state_store: StateStore, subject: HardwareStopper, + movement: MovementHandler, ) -> None: """Don't drop tip when there aren't any tips attached to pipettes.""" decoy.when(state_store.pipettes.get_all_attached_tips()).then_return([]) @@ -132,7 +133,10 @@ async def test_hardware_stopping_sequence_without_pipette_tips( ) decoy.verify( - await hardware_api.stop(home_after=True), + await hardware_api.stop(home_after=False), + await movement.home( + [MotorAxis.X, MotorAxis.Y, MotorAxis.LEFT_Z, MotorAxis.RIGHT_Z] + ), ) @@ -171,6 +175,7 @@ async def test_hardware_stopping_sequence_no_pipette( state_store: StateStore, hardware_api: HardwareAPI, mock_tip_handler: TipHandler, + movement: MovementHandler, subject: HardwareStopper, ) -> None: """It should gracefully no-op if the HW API reports no attached pipette.""" @@ -193,8 +198,14 @@ async def test_hardware_stopping_sequence_no_pipette( ) decoy.verify( - await hardware_api.stop(home_after=True), - times=1, + await hardware_api.stop(home_after=False), + await movement.home( + [MotorAxis.X, MotorAxis.Y, MotorAxis.LEFT_Z, MotorAxis.RIGHT_Z] + ), + await hardware_api.stop(home_after=False), + await movement.home( + [MotorAxis.X, MotorAxis.Y, MotorAxis.LEFT_Z, MotorAxis.RIGHT_Z] + ), ) @@ -232,7 +243,11 @@ async def test_hardware_stopping_sequence_with_gripper( await movement.home( axes=[MotorAxis.X, MotorAxis.Y, MotorAxis.LEFT_Z, MotorAxis.RIGHT_Z] ), - await ot3_hardware_api.stop(home_after=True), + await ot3_hardware_api.stop(home_after=False), + await ot3_hardware_api.home_z(mount=OT3Mount.GRIPPER), + await movement.home( + axes=[MotorAxis.X, MotorAxis.Y, MotorAxis.LEFT_Z, MotorAxis.RIGHT_Z] + ), ) @@ -284,7 +299,11 @@ async def test_hardware_stopping_sequence_with_fixed_trash( pipette_id="pipette-id", home_after=False, ), - await ot3_hardware_api.stop(home_after=True), + await ot3_hardware_api.stop(home_after=False), + await ot3_hardware_api.home_z(mount=OT3Mount.GRIPPER), + await movement.home( + axes=[MotorAxis.X, MotorAxis.Y, MotorAxis.LEFT_Z, MotorAxis.RIGHT_Z] + ), ) @@ -336,5 +355,8 @@ async def test_hardware_stopping_sequence_with_OT2_addressable_area( pipette_id="pipette-id", home_after=False, ), - await hardware_api.stop(home_after=True), + await hardware_api.stop(home_after=False), + await movement.home( + axes=[MotorAxis.X, MotorAxis.Y, MotorAxis.LEFT_Z, MotorAxis.RIGHT_Z] + ), ) diff --git a/api/tests/opentrons/protocol_engine/execution/test_tip_handler.py b/api/tests/opentrons/protocol_engine/execution/test_tip_handler.py index b04bdd25b67..d3e844ee046 100644 --- a/api/tests/opentrons/protocol_engine/execution/test_tip_handler.py +++ b/api/tests/opentrons/protocol_engine/execution/test_tip_handler.py @@ -257,7 +257,9 @@ async def test_drop_tip( await subject.drop_tip(pipette_id="pipette-id", home_after=True) decoy.verify( - await mock_hardware_api.tip_drop_moves(mount=Mount.RIGHT, home_after=True) + await mock_hardware_api.tip_drop_moves( + mount=Mount.RIGHT, ignore_plunger=False, home_after=True + ) ) decoy.verify(mock_hardware_api.remove_tip(mount=Mount.RIGHT)) decoy.verify( diff --git a/app-shell-odd/src/config/__fixtures__/index.ts b/app-shell-odd/src/config/__fixtures__/index.ts index 7f9a48dc02c..1b05dfed7a6 100644 --- a/app-shell-odd/src/config/__fixtures__/index.ts +++ b/app-shell-odd/src/config/__fixtures__/index.ts @@ -13,6 +13,7 @@ import type { ConfigV23, ConfigV24, ConfigV25, + ConfigV26, } from '@opentrons/app/src/redux/config/types' const PKG_VERSION: string = _PKG_VERSION_ @@ -181,3 +182,12 @@ export const MOCK_CONFIG_V25: ConfigV25 = { systemLanguage: null, }, } + +export const MOCK_CONFIG_V26: ConfigV26 = { + ...MOCK_CONFIG_V25, + version: 26, + onDeviceDisplaySettings: { + ...MOCK_CONFIG_V25.onDeviceDisplaySettings, + unfinishedUnboxingFlowRoute: '/choose-language', + }, +} diff --git a/app-shell-odd/src/config/__tests__/migrate.test.ts b/app-shell-odd/src/config/__tests__/migrate.test.ts index 7ea91ee8d53..f1be25b5fe9 100644 --- a/app-shell-odd/src/config/__tests__/migrate.test.ts +++ b/app-shell-odd/src/config/__tests__/migrate.test.ts @@ -17,13 +17,14 @@ import { MOCK_CONFIG_V23, MOCK_CONFIG_V24, MOCK_CONFIG_V25, + MOCK_CONFIG_V26, } from '../__fixtures__' import { migrate } from '../migrate' vi.mock('uuid/v4') -const NEWEST_VERSION = 25 -const NEWEST_MOCK_CONFIG = MOCK_CONFIG_V25 +const NEWEST_VERSION = 26 +const NEWEST_MOCK_CONFIG = MOCK_CONFIG_V26 describe('config migration', () => { beforeEach(() => { @@ -129,10 +130,17 @@ describe('config migration', () => { expect(result.version).toBe(NEWEST_VERSION) expect(result).toEqual(NEWEST_MOCK_CONFIG) }) - it('should keep version 25', () => { + it('should migrate version 25 to latest', () => { const v25Config = MOCK_CONFIG_V25 const result = migrate(v25Config) + expect(result.version).toBe(NEWEST_VERSION) + expect(result).toEqual(NEWEST_MOCK_CONFIG) + }) + it('should keep version 26', () => { + const v26Config = MOCK_CONFIG_V26 + const result = migrate(v26Config) + expect(result.version).toBe(NEWEST_VERSION) expect(result).toEqual(NEWEST_MOCK_CONFIG) }) diff --git a/app-shell-odd/src/config/migrate.ts b/app-shell-odd/src/config/migrate.ts index b6977fbf489..48d30e1297a 100644 --- a/app-shell-odd/src/config/migrate.ts +++ b/app-shell-odd/src/config/migrate.ts @@ -18,13 +18,14 @@ import type { ConfigV23, ConfigV24, ConfigV25, + ConfigV26, } from '@opentrons/app/src/redux/config/types' // format // base config v12 defaults // any default values for later config versions are specified in the migration // functions for those version below -const CONFIG_VERSION_LATEST = 25 // update this after each config version bump +const CONFIG_VERSION_LATEST = 26 // update this after each config version bump const PKG_VERSION: string = _PKG_VERSION_ export const DEFAULTS_V12: ConfigV12 = { @@ -238,6 +239,21 @@ const toVersion25 = (prevConfig: ConfigV24): ConfigV25 => { } return nextConfig } +const toVersion26 = (prevConfig: ConfigV25): ConfigV26 => { + const nextConfig = { + ...prevConfig, + version: 26 as const, + onDeviceDisplaySettings: { + ...prevConfig.onDeviceDisplaySettings, + unfinishedUnboxingFlowRoute: + prevConfig.onDeviceDisplaySettings.unfinishedUnboxingFlowRoute === + '/welcome' + ? '/choose-language' + : prevConfig.onDeviceDisplaySettings.unfinishedUnboxingFlowRoute, + }, + } + return nextConfig +} const MIGRATIONS: [ (prevConfig: ConfigV12) => ConfigV13, @@ -252,7 +268,8 @@ const MIGRATIONS: [ (prevConfig: ConfigV21) => ConfigV22, (prevConfig: ConfigV22) => ConfigV23, (prevConfig: ConfigV23) => ConfigV24, - (prevConfig: ConfigV24) => ConfigV25 + (prevConfig: ConfigV24) => ConfigV25, + (prevConfig: ConfigV25) => ConfigV26 ] = [ toVersion13, toVersion14, @@ -267,6 +284,7 @@ const MIGRATIONS: [ toVersion23, toVersion24, toVersion25, + toVersion26, ] export const DEFAULTS: Config = migrate(DEFAULTS_V12) @@ -287,6 +305,7 @@ export function migrate( | ConfigV23 | ConfigV24 | ConfigV25 + | ConfigV26 ): Config { let result = prevConfig // loop through the migrations, skipping any migrations that are unnecessary diff --git a/app-shell/build/release-notes.md b/app-shell/build/release-notes.md index 9b9231e9709..4d5c7827f6f 100644 --- a/app-shell/build/release-notes.md +++ b/app-shell/build/release-notes.md @@ -8,6 +8,22 @@ By installing and using Opentrons software, you agree to the Opentrons End-User --- +## Opentrons App Changes in 8.3.0 + +Welcome to the v8.3.0 release of the Opentrons App! This release adds support for Evosep Evotips on the Flex, as well as other features. + +### New Features + +- Use Evosep Evotips in Python API version 2.22 protocols for protein sample purification. Only available with the Flex 96-channel pipette. +- Change the app or Flex touchscreen language to Mandarin in Settings. +- Load a newly modified Flex 8-Channel EM 1000 µL pipette equipped with a PEEK motor component to automate emulsion applications. + +### Improved Features + +- Improvements to the Flex error recovery feature help protocols recover from detected stalls and collisions, saving you valuable time and resources. + +--- + ## Opentrons App Changes in 8.2.0 Welcome to the v8.2.0 release of the Opentrons App! This release adds support for the Opentrons Absorbance Plate Reader Module, as well as other features. diff --git a/app-shell/electron-builder.config.js b/app-shell/electron-builder.config.js index decac1f66b9..26bcf518e28 100644 --- a/app-shell/electron-builder.config.js +++ b/app-shell/electron-builder.config.js @@ -1,11 +1,7 @@ 'use strict' const path = require('path') -const { - OT_APP_DEPLOY_BUCKET, - OT_APP_DEPLOY_FOLDER, - APPLE_TEAM_ID, -} = process.env +const { OT_APP_DEPLOY_BUCKET, OT_APP_DEPLOY_FOLDER } = process.env const DEV_MODE = process.env.NODE_ENV !== 'production' const USE_PYTHON = process.env.NO_PYTHON !== 'true' const WINDOWS_SIGN = process.env.WINDOWS_SIGN === 'true' @@ -62,9 +58,7 @@ module.exports = async () => ({ icon: project === 'robot-stack' ? 'build/icon.icns' : 'build/three.icns', forceCodeSigning: !DEV_MODE, gatekeeperAssess: true, - notarize: { - teamId: APPLE_TEAM_ID, - }, + // note: notarize.teamId is passed by implicitly sending through the APPLE_TEAM_ID env var }, dmg: { icon: null, diff --git a/app-shell/src/__fixtures__/config.ts b/app-shell/src/__fixtures__/config.ts index dd344c78532..197f594fcd3 100644 --- a/app-shell/src/__fixtures__/config.ts +++ b/app-shell/src/__fixtures__/config.ts @@ -25,6 +25,7 @@ import type { ConfigV23, ConfigV24, ConfigV25, + ConfigV26, } from '@opentrons/app/src/redux/config/types' export const MOCK_CONFIG_V0: ConfigV0 = { @@ -312,3 +313,8 @@ export const MOCK_CONFIG_V25: ConfigV25 = { systemLanguage: null, }, } + +export const MOCK_CONFIG_V26: ConfigV26 = { + ...MOCK_CONFIG_V25, + version: 26, +} diff --git a/app-shell/src/config/__tests__/migrate.test.ts b/app-shell/src/config/__tests__/migrate.test.ts index ddc151fc2cf..b61210561c5 100644 --- a/app-shell/src/config/__tests__/migrate.test.ts +++ b/app-shell/src/config/__tests__/migrate.test.ts @@ -29,13 +29,14 @@ import { MOCK_CONFIG_V23, MOCK_CONFIG_V24, MOCK_CONFIG_V25, + MOCK_CONFIG_V26, } from '../../__fixtures__' import { migrate } from '../migrate' vi.mock('uuid/v4') -const NEWEST_VERSION = 25 -const NEWEST_MOCK_CONFIG = MOCK_CONFIG_V25 +const NEWEST_VERSION = 26 +const NEWEST_MOCK_CONFIG = MOCK_CONFIG_V26 describe('config migration', () => { beforeEach(() => { @@ -234,10 +235,17 @@ describe('config migration', () => { expect(result.version).toBe(NEWEST_VERSION) expect(result).toEqual(NEWEST_MOCK_CONFIG) }) - it('should keep version 25', () => { + it('should migrate version 25 to latest', () => { const v25Config = MOCK_CONFIG_V25 const result = migrate(v25Config) + expect(result.version).toBe(NEWEST_VERSION) + expect(result).toEqual(NEWEST_MOCK_CONFIG) + }) + it('should keep version 26', () => { + const v26Config = MOCK_CONFIG_V26 + const result = migrate(v26Config) + expect(result.version).toBe(NEWEST_VERSION) expect(result).toEqual(NEWEST_MOCK_CONFIG) }) diff --git a/app-shell/src/config/migrate.ts b/app-shell/src/config/migrate.ts index 69c53ab2e72..1ad6f4900cb 100644 --- a/app-shell/src/config/migrate.ts +++ b/app-shell/src/config/migrate.ts @@ -29,13 +29,14 @@ import type { ConfigV23, ConfigV24, ConfigV25, + ConfigV26, } from '@opentrons/app/src/redux/config/types' // format // base config v0 defaults // any default values for later config versions are specified in the migration // functions for those version below -const CONFIG_VERSION_LATEST = 25 +const CONFIG_VERSION_LATEST = 26 export const DEFAULTS_V0: ConfigV0 = { version: 0, @@ -443,6 +444,14 @@ const toVersion25 = (prevConfig: ConfigV24): ConfigV25 => { return nextConfig } +const toVersion26 = (prevConfig: ConfigV25): ConfigV26 => { + const nextConfig = { + ...prevConfig, + version: 26 as const, + } + return nextConfig +} + const MIGRATIONS: [ (prevConfig: ConfigV0) => ConfigV1, (prevConfig: ConfigV1) => ConfigV2, @@ -468,7 +477,8 @@ const MIGRATIONS: [ (prevConfig: ConfigV21) => ConfigV22, (prevConfig: ConfigV22) => ConfigV23, (prevConfig: ConfigV23) => ConfigV24, - (prevConfig: ConfigV24) => ConfigV25 + (prevConfig: ConfigV24) => ConfigV25, + (prevConfig: ConfigV25) => ConfigV26 ] = [ toVersion1, toVersion2, @@ -495,6 +505,7 @@ const MIGRATIONS: [ toVersion23, toVersion24, toVersion25, + toVersion26, ] export const DEFAULTS: Config = migrate(DEFAULTS_V0) @@ -527,6 +538,7 @@ export function migrate( | ConfigV23 | ConfigV24 | ConfigV25 + | ConfigV26 ): Config { const prevVersion = prevConfig.version let result = prevConfig diff --git a/app-shell/src/protocol-storage/__tests__/file-system.test.ts b/app-shell/src/protocol-storage/__tests__/file-system.test.ts index 4da2cd23abe..cc742e0b89b 100644 --- a/app-shell/src/protocol-storage/__tests__/file-system.test.ts +++ b/app-shell/src/protocol-storage/__tests__/file-system.test.ts @@ -109,66 +109,67 @@ describe('protocol storage directory utilities', () => { }) describe('parseProtocolDirs', () => { - it('reads and parses directories', () => { + it('reads and parses directories', async () => { const protocolsDir = makeEmptyDir() - const firstProtocolDirName = 'protocol_item_1' const secondProtocolDirName = 'protocol_item_2' - const firstDirPath = path.join(protocolsDir, firstProtocolDirName) const secondDirPath = path.join(protocolsDir, secondProtocolDirName) - return Promise.all([ - fs.emptyDir(path.join(protocolsDir, firstProtocolDirName)), - fs.emptyDir(path.join(protocolsDir, firstProtocolDirName, 'src')), - fs.createFile( - path.join(protocolsDir, firstProtocolDirName, 'src', 'main.py') - ), - fs.emptyDir(path.join(protocolsDir, firstProtocolDirName, 'analysis')), - fs.createFile( - path.join( - protocolsDir, - firstProtocolDirName, - 'analysis', - 'fake_timestamp0.json' - ) - ), - fs.emptyDir(path.join(protocolsDir, secondProtocolDirName)), - fs.emptyDir(path.join(protocolsDir, secondProtocolDirName, 'src')), - fs.createFile( - path.join(protocolsDir, secondProtocolDirName, 'src', 'main.json') - ), - fs.emptyDir(path.join(protocolsDir, secondProtocolDirName, 'analysis')), - fs.createFile( - path.join( - protocolsDir, - secondProtocolDirName, - 'analysis', - 'fake_timestamp1.json' - ) - ), - ]).then(() => { - return expect( - parseProtocolDirs([firstDirPath, secondDirPath]) - ).resolves.toEqual([ - { - dirPath: firstDirPath, - modified: expect.any(Number), - srcFilePaths: [path.join(firstDirPath, 'src', 'main.py')], - analysisFilePaths: [ - path.join(firstDirPath, 'analysis', 'fake_timestamp0.json'), - ], - }, - { - dirPath: secondDirPath, - modified: expect.any(Number), - srcFilePaths: [path.join(secondDirPath, 'src', 'main.json')], - analysisFilePaths: [ - path.join(secondDirPath, 'analysis', 'fake_timestamp1.json'), - ], - }, - ]) - }) + await fs.emptyDir(path.join(protocolsDir, firstProtocolDirName)) + await fs.emptyDir(path.join(protocolsDir, firstProtocolDirName, 'src')) + await fs.emptyDir( + path.join(protocolsDir, firstProtocolDirName, 'analysis') + ) + await fs.createFile( + path.join(protocolsDir, firstProtocolDirName, 'src', 'main.py') + ) + await fs.createFile( + path.join( + protocolsDir, + firstProtocolDirName, + 'analysis', + 'fake_timestamp0.json' + ) + ) + + await fs.emptyDir(path.join(protocolsDir, secondProtocolDirName)) + await fs.emptyDir(path.join(protocolsDir, secondProtocolDirName, 'src')) + await fs.emptyDir( + path.join(protocolsDir, secondProtocolDirName, 'analysis') + ) + await fs.createFile( + path.join(protocolsDir, secondProtocolDirName, 'src', 'main.json') + ) + await fs.createFile( + path.join( + protocolsDir, + secondProtocolDirName, + 'analysis', + 'fake_timestamp1.json' + ) + ) + + const result = await parseProtocolDirs([firstDirPath, secondDirPath]) + + expect(result).toEqual([ + { + dirPath: firstDirPath, + modified: expect.any(Number), + srcFilePaths: [path.join(firstDirPath, 'src', 'main.py')], + analysisFilePaths: [ + path.join(firstDirPath, 'analysis', 'fake_timestamp0.json'), + ], + }, + { + dirPath: secondDirPath, + modified: expect.any(Number), + srcFilePaths: [path.join(secondDirPath, 'src', 'main.json')], + analysisFilePaths: [ + path.join(secondDirPath, 'analysis', 'fake_timestamp1.json'), + ], + }, + ]) }) }) diff --git a/app/src/App/DesktopApp.tsx b/app/src/App/DesktopApp.tsx index 196a6cf547c..029ec99ee26 100644 --- a/app/src/App/DesktopApp.tsx +++ b/app/src/App/DesktopApp.tsx @@ -1,5 +1,4 @@ import { useState, Fragment } from 'react' -import { useTranslation } from 'react-i18next' import { Navigate, Route, Routes, useMatch } from 'react-router-dom' import { ErrorBoundary } from 'react-error-boundary' import { @@ -44,7 +43,6 @@ import { useFeatureFlag } from '../redux/config' import type { RouteProps } from './types' export const DesktopApp = (): JSX.Element => { - const { t } = useTranslation('top_navigation') useSoftwareUpdatePoll() const [ isEmergencyStopModalDismissed, @@ -70,55 +68,55 @@ export const DesktopApp = (): JSX.Element => { const desktopRoutes: RouteProps[] = [ { Component: ProtocolsLanding, - name: t('protocols'), + name: 'protocols', navLinkTo: '/protocols', path: '/protocols', }, { Component: ProtocolDetails, - name: t('protocol_details'), + name: 'Protocol Details', path: '/protocols/:protocolKey', }, { Component: ProtocolTimeline, - name: t('protocol_timeline'), + name: 'Protocol Timeline', path: '/protocols/:protocolKey/timeline', }, { Component: Labware, - name: t('labware'), + name: 'labware', navLinkTo: '/labware', path: '/labware', }, { Component: DevicesLanding, - name: t('devices'), + name: 'devices', navLinkTo: '/devices', path: '/devices', }, { Component: DeviceDetails, - name: t('device'), + name: 'Device', path: '/devices/:robotName', }, { Component: RobotSettings, - name: t('robot_settings'), + name: 'Robot Settings', path: '/devices/:robotName/robot-settings/:robotSettingsTab?', }, { Component: CalibrationDashboard, - name: t('calibration_dashboard'), + name: 'Calibration Dashboard', path: '/devices/:robotName/robot-settings/calibration/dashboard', }, { Component: ProtocolRunDetails, - name: t('run_details'), + name: 'Run Details', path: '/devices/:robotName/protocol-runs/:runId/:protocolRunDetailsTab?', }, { Component: AppSettings, - name: t('app_settings'), + name: 'App Settings', path: '/app-settings/:appSettingsTab?', }, ] diff --git a/app/src/App/Navbar.tsx b/app/src/App/Navbar.tsx index 90e62b608ae..ebef216e9f8 100644 --- a/app/src/App/Navbar.tsx +++ b/app/src/App/Navbar.tsx @@ -1,4 +1,5 @@ import { useCallback } from 'react' +import { useTranslation } from 'react-i18next' import { NavLink, useNavigate } from 'react-router-dom' import styled from 'styled-components' import debounce from 'lodash/debounce' @@ -111,11 +112,11 @@ const LogoImg = styled('img')` ` export function Navbar({ routes }: { routes: RouteProps[] }): JSX.Element { + const { t } = useTranslation('top_navigation') const navigate = useNavigate() const navRoutes = routes.filter( ({ navLinkTo }: RouteProps) => navLinkTo != null ) - const debouncedNavigate = useCallback( debounce((path: string) => { navigate(path) @@ -149,7 +150,7 @@ export function Navbar({ routes }: { routes: RouteProps[] }): JSX.Element { as="h3" margin={`${SPACING.spacing8} 0 ${SPACING.spacing8} ${SPACING.spacing12}`} > - {name} + {t(name)} ))} diff --git a/app/src/assets/localization/en/app_settings.json b/app/src/assets/localization/en/app_settings.json index c6c4b595597..540df5ef394 100644 --- a/app/src/assets/localization/en/app_settings.json +++ b/app/src/assets/localization/en/app_settings.json @@ -117,7 +117,7 @@ "usb_to_ethernet_unknown_manufacturer": "Unknown Manufacturer", "usb_to_ethernet_unknown_product": "Unknown Adapter", "use_system_language": "Use system language", - "view_software_update": "View software update", "view_adapter_info": "view adapter info", + "view_software_update": "View software update", "view_update": "View Update" } diff --git a/app/src/assets/localization/en/change_pipette.json b/app/src/assets/localization/en/change_pipette.json index b9ca35752d5..f63445ea779 100644 --- a/app/src/assets/localization/en/change_pipette.json +++ b/app/src/assets/localization/en/change_pipette.json @@ -1,8 +1,8 @@ { "are_you_sure_exit": "Are you sure you want to exit before {{direction}} your pipette?", "attach_name_pipette": "Attach a {{pipette}} Pipette", - "attach_pipette_type": "Attach a {{pipetteName}} Pipette", "attach_pipette": "Attach a pipette", + "attach_pipette_type": "Attach a {{pipetteName}} Pipette", "attach_the_pipette": "

Attach the pipette

Push in the white connector tab until you feel it plug into the pipette.", "attached_pipette_does_not_match": "The attached {{name}} does not match the {{pipette}} you had originally selected.", "attaching": "attaching", @@ -16,10 +16,10 @@ "confirming_attachment": "Confirming attachment", "confirming_detachment": "Confirming detachment", "continue": "Continue", - "detach_pipette_from_mount": "Detach Pipette from {{mount}} Mount", + "detach": "Detach pipette", "detach_pipette": "Detach {{pipette}} from {{mount}} Mount", + "detach_pipette_from_mount": "Detach Pipette from {{mount}} Mount", "detach_try_again": "Detach and try again", - "detach": "Detach pipette", "detaching": "detaching", "get_started": "Get started", "go_back": "Go back", diff --git a/app/src/assets/localization/en/device_details.json b/app/src/assets/localization/en/device_details.json index 58bc0ed4d84..11ecc8edc2b 100644 --- a/app/src/assets/localization/en/device_details.json +++ b/app/src/assets/localization/en/device_details.json @@ -1,16 +1,16 @@ { "about_gripper": "About gripper", "about_module": "About {{name}}", - "about_pipette_name": "About {{name}} Pipette", "about_pipette": "About pipette", - "abs_reader_status": "Absorbance Plate Reader Status", + "about_pipette_name": "About {{name}} Pipette", "abs_reader_lid_status": "Lid status: {{status}}", + "abs_reader_status": "Absorbance Plate Reader Status", + "add": "Add", "add_fixture_description": "Add this hardware to your deck configuration. It will be referenced during protocol analysis.", "add_to_slot": "Add to slot {{slotName}}", - "add": "Add", + "an_error_occurred_while_updating": "An error occurred while updating your pipette's settings.", "an_error_occurred_while_updating_module": "An error occurred while updating your {{moduleName}}. Please try again.", "an_error_occurred_while_updating_please_try_again": "An error occurred while updating your pipette's settings. Please try again.", - "an_error_occurred_while_updating": "An error occurred while updating your pipette's settings.", "attach_gripper": "Attach gripper", "attach_pipette": "Attach pipette", "bad_run": "run could not be loaded", @@ -18,13 +18,13 @@ "bundle_firmware_file_not_found": "Bundled fw file not found for module of type: {{module}}", "calibrate_gripper": "Calibrate gripper", "calibrate_now": "Calibrate now", - "calibrate_pipette_offset": "Calibrate pipette offset", "calibrate_pipette": "Calibrate pipette", - "calibration_needed_without_link": "Calibration needed.", + "calibrate_pipette_offset": "Calibrate pipette offset", "calibration_needed": "Calibration needed. Calibrate now", + "calibration_needed_without_link": "Calibration needed.", "canceled": "canceled", - "changes_will_be_lost_description": "Are you sure you want to exit without saving your deck configuration?", "changes_will_be_lost": "Changes will be lost", + "changes_will_be_lost_description": "Are you sure you want to exit without saving your deck configuration?", "choose_protocol_to_run": "Choose protocol to Run on {{name}}", "close_lid": "Close lid", "completed": "completed", @@ -36,9 +36,9 @@ "current_temp": "Current: {{temp}} °C", "current_version": "Current Version", "deck_cal_missing": "Pipette Offset calibration missing. Calibrate deck first.", + "deck_configuration": "deck configuration", "deck_configuration_is_not_available_when_robot_is_busy": "Deck configuration is not available when the robot is busy", "deck_configuration_is_not_available_when_run_is_in_progress": "Deck configuration is not available when run is in progress", - "deck_configuration": "deck configuration", "deck_fixture_setup_instructions": "Deck fixture setup instructions", "deck_fixture_setup_modal_bottom_description_desktop": "For detailed instructions for different types of fixtures, scan the QR code or go to the link below.", "deck_fixture_setup_modal_top_description": "First, unscrew and remove the deck slot where you'll install a fixture. Then put the fixture in place and attach it as needed.", @@ -58,15 +58,15 @@ "estop_pressed": "E-stop pressed. Robot movement is halted.", "failed": "failed", "files": "Files", - "firmware_update_needed": "Instrument firmware update needed. Start the update on the robot's touchscreen.", "firmware_update_available": "Firmware update available.", "firmware_update_failed": "Failed to update module firmware", - "firmware_updated_successfully": "Firmware updated successfully", + "firmware_update_needed": "Instrument firmware update needed. Start the update on the robot's touchscreen.", "firmware_update_occurring": "Firmware update in progress...", + "firmware_updated_successfully": "Firmware updated successfully", "fixture": "Fixture", "flex_stacker_door_status": "Door status: {{status}}", - "have_not_run_description": "After you run some protocols, they will appear here.", "have_not_run": "No recent runs", + "have_not_run_description": "After you run some protocols, they will appear here.", "heater": "Heater", "height_ranges": "{{gen}} Height Ranges", "hot_to_the_touch": "Module is hot to the touch", @@ -75,12 +75,12 @@ "instruments_and_modules": "Instruments and Modules", "labware_bottom": "Labware Bottom", "last_run_time": "last run {{number}}", - "left_right": "Left + Right Mounts", "left": "left", + "left_right": "Left + Right Mounts", "lights": "Lights", "link_firmware_update": "View Firmware Update", - "location_conflicts": "Location conflicts", "location": "Location", + "location_conflicts": "Location conflicts", "magdeck_gen1_height": "Height: {{height}}", "magdeck_gen2_height": "Height: {{height}} mm", "max_engage_height": "Max Engage Height", @@ -89,13 +89,13 @@ "missing_hardware": "missing hardware", "missing_instrument": "missing {{num}} instrument", "missing_instruments_plural": "missing {{count}} instruments", - "missing_module_plural": "missing {{count}} modules", "missing_module": "missing {{num}} module", + "missing_module_plural": "missing {{count}} modules", "module_actions_unavailable": "Module actions unavailable while protocol is running", + "module_calibration_required": "Module calibration required.", "module_calibration_required_no_pipette_attached": "Module calibration required. Attach a pipette before running module calibration.", "module_calibration_required_no_pipette_calibrated": "Module calibration required. Calibrate pipette before running module calibration. ", "module_calibration_required_update_pipette_FW": "Update pipette firmware before proceeding with required module calibration.", - "module_calibration_required": "Module calibration required.", "module_controls": "Module Controls", "module_error": "Module error", "module_name_error": "{{moduleName}} error", @@ -106,8 +106,8 @@ "no_deck_fixtures": "No deck fixtures", "no_protocol_runs": "No protocol runs yet!", "no_protocols_found": "No protocols found", - "no_recent_runs_description": "After you run some protocols, they will appear here.", "no_recent_runs": "No recent runs", + "no_recent_runs_description": "After you run some protocols, they will appear here.", "num_units": "{{num}} mm", "offline_deck_configuration": "Robot must be on the network to see deck configuration", "offline_instruments_and_modules": "Robot must be on the network to see connected instruments and modules", @@ -133,32 +133,32 @@ "protocol_analysis_failed": "Protocol failed in-app analysis. ", "protocol_analysis_stale": "Protocol analysis out of date. ", "protocol_details_page_reanalyze": "Go to the protocol details screen to reanalyze.", - "ready_to_run": "ready to run", "ready": "Ready", + "ready_to_run": "ready to run", "recalibrate_gripper": "Recalibrate gripper", "recalibrate_now": "Recalibrate now", - "recalibrate_pipette_offset": "Recalibrate pipette offset", "recalibrate_pipette": "Recalibrate pipette", + "recalibrate_pipette_offset": "Recalibrate pipette offset", "recent_protocol_runs": "Recent Protocol Runs", - "rerun_now": "Rerun protocol now", "rerun_loading": "Protocol re-run is disabled until data connection fully loads", + "rerun_now": "Rerun protocol now", "reset_all": "Reset all", "reset_estop": "Reset E-stop", "resume_operation": "Resume operation", "right": "right", "robot_control_not_available": "Some robot controls are not available when run is in progress", "robot_initializing": "Initializing...", + "run": "Run", "run_a_protocol": "Run a protocol", "run_again": "Run again", "run_duration": "Run duration", - "run": "Run", "select_options": "Select options", "serial_number": "Serial Number", "set_block_temp": "Set temperature", "set_block_temperature": "Set block temperature", + "set_engage_height": "Set Engage Height", "set_engage_height_and_enter_integer": "Set the engage height for this Magnetic Module. Enter an integer between {{lower}} and {{higher}}.", "set_engage_height_for_module": "Set Engage Height for {{name}}", - "set_engage_height": "Set Engage Height", "set_lid_temperature": "Set lid temperature", "set_shake_of_hs": "Set rpm for this module.", "set_shake_speed": "Set shake speed", @@ -175,8 +175,8 @@ "target_temp": "Target: {{temp}} °C", "tc_block": "Block", "tc_lid": "Lid", - "tc_set_temperature_body": "Pre heat or cool your Thermocycler {{part}}. Enter a whole number between {{min}} °C and {{max}} °C.", "tc_set_temperature": "Set {{part}} Temperature for {{name}}", + "tc_set_temperature_body": "Pre heat or cool your Thermocycler {{part}}. Enter a whole number between {{min}} °C and {{max}} °C.", "tempdeck_slideout_body": "Pre heat or cool your {{model}}. Enter a whole number between 4 °C and 96 °C.", "tempdeck_slideout_title": "Set Temperature for {{name}}", "temperature": "Temperature", @@ -189,9 +189,9 @@ "usb_port_not_connected": "usb not connected", "usb_port": "usb-{{port}}{{hubPort}}", "version": "Version {{version}}", + "view": "View", "view_pipette_setting": "Pipette Settings", "view_run_record": "View protocol run record", - "view": "View", "waste_chute": "Waste chute", "welcome_modal_description": "A place to run protocols, manage your instruments, and view robot status.", "welcome_to_your_dashboard": "Welcome to your dashboard!", diff --git a/app/src/assets/localization/en/device_settings.json b/app/src/assets/localization/en/device_settings.json index 06a67d39d35..e0a199fbee4 100644 --- a/app/src/assets/localization/en/device_settings.json +++ b/app/src/assets/localization/en/device_settings.json @@ -318,8 +318,8 @@ "unable_to_commit_update": "Unable to commit update", "unable_to_connect": "Unable to connect to Wi-Fi", "unable_to_disconnect": "Unable to disconnect from Wi-Fi", - "unable_to_find_system_file": "Unable to find system file for update", "unable_to_find_robot_with_name": "Unable to find online robot with name", + "unable_to_find_system_file": "Unable to find system file for update", "unable_to_restart": "Unable to restart robot", "unable_to_start_update_session": "Unable to start update session", "up_to_date": "up to date", diff --git a/app/src/assets/localization/en/error_recovery.json b/app/src/assets/localization/en/error_recovery.json index e4e1b5164eb..3f22e2e63f9 100644 --- a/app/src/assets/localization/en/error_recovery.json +++ b/app/src/assets/localization/en/error_recovery.json @@ -110,7 +110,7 @@ "stand_back_retrying": "Stand back, retrying failed step", "stand_back_skipping_to_next_step": "Stand back, skipping to next step", "take_any_necessary_precautions": "Take any necessary precautions before positioning yourself to stabilize or catch the labware. Once confirmed, a countdown will begin before the gripper releases.", - "take_necessary_actions": "First, take any necessary actions to prepare the robot to retry the failed step.Then, close the robot door before proceeding.", + "take_necessary_actions": "Take any necessary additional actions to prepare the robot to retry the failed step.Close the robot door before proceeding.", "take_necessary_actions_failed_pickup": "First, take any necessary actions to prepare the robot to retry the failed tip pickup.Then, close the robot door before proceeding.", "take_necessary_actions_failed_tip_drop": "First, take any necessary actions to prepare the robot to retry the failed tip drop.Then, close the robot door before proceeding.", "take_necessary_actions_home": "Take any necessary actions to prepare the robot to move the gantry to its home position.Close the robot door before proceeding.", diff --git a/app/src/assets/localization/en/gripper_wizard_flows.json b/app/src/assets/localization/en/gripper_wizard_flows.json index 70df5688820..929627bf064 100644 --- a/app/src/assets/localization/en/gripper_wizard_flows.json +++ b/app/src/assets/localization/en/gripper_wizard_flows.json @@ -10,8 +10,8 @@ "continue": "Continue", "continue_calibration": "Continue calibration", "detach_gripper": "Detach Gripper", - "firmware_updating": "A firmware update is required, instrument is updating...", "firmware_up_to_date": "Firmware is up to date.", + "firmware_updating": "A firmware update is required, instrument is updating...", "get_started": "Get started", "gripper_calibration": "Gripper Calibration", "gripper_recalibration": "Gripper Recalibration", diff --git a/app/src/assets/localization/en/heater_shaker.json b/app/src/assets/localization/en/heater_shaker.json index 12ac83a4123..0eec55e6a11 100644 --- a/app/src/assets/localization/en/heater_shaker.json +++ b/app/src/assets/localization/en/heater_shaker.json @@ -4,43 +4,43 @@ "cannot_shake": "Cannot shake when labware latch is open", "close_labware_latch": "Close labware latch", "close_latch": "Close latch", - "closed_and_locked": "Closed and Locked", "closed": "Closed", + "closed_and_locked": "Closed and Locked", "closing": "Closing...", "complete": "Complete", "confirm_attachment": "Confirm attachment", "confirm_heater_shaker_modal_attachment": "Confirm Heater-Shaker Module attachment", "continue_shaking_protocol_start_prompt": "Continue shaking while the protocol starts?", + "deactivate": "Deactivate", "deactivate_heater": "Deactivate heater", "deactivate_shaker": "Deactivate shaker", - "deactivate": "Deactivate", "heater_shaker_in_slot": "Attach {{moduleName}} in Slot {{slotName}} before proceeding", "heater_shaker_is_shaking": "Heater-Shaker Module is currently shaking", "keep_shaking_start_run": "Keep shaking and start run", - "labware_latch": "Labware Latch", "labware": "Labware", + "labware_latch": "Labware Latch", "min_max_rpm": "{{min}} - {{max}} rpm", "module_anchors_extended": "Before the run begins, module should have both anchors fully extended for a firm attachment to the deck.", "module_in_slot": "{{moduleName}} in Slot {{slotName}}", "module_should_have_anchors": "Module should have both anchors fully extended for a firm attachment to the deck.", + "open": "Open", "open_labware_latch": "Open labware latch", "open_latch": "Open latch", - "open": "Open", "opening": "Opening...", "proceed_to_run": "Proceed to run", "set_shake_speed": "Set shake speed", "set_temperature": "Set module temperature", "shake_speed": "Shake speed", "show_attachment_instructions": "Show attachment instructions", - "stop_shaking_start_run": "Stop shaking and start run", "stop_shaking": "Stop Shaking", + "stop_shaking_start_run": "Stop shaking and start run", "t10_torx_screwdriver": "{{name}} Screwdriver", "t10_torx_screwdriver_subtitle": "Provided with the Heater-Shaker. Using another size can strip the module's screws.", + "test_shake": "Test shake", "test_shake_banner_information": "If you want to add labware to the module before doing a test shake, you can use the labware latch controls to hold the latches open.", "test_shake_banner_labware_information": "If you want to add the {{labware}} to the module before doing a test shake, you can use the labware latch controls.", "test_shake_slideout_banner_info": "If you want to add labware to the module before doing a test shake, you can use the labware latch controls to hold the latches open.", "test_shake_troubleshooting_slideout_description": "Revisit instructions for attaching the module to the deck as well as attaching the thermal adapter.", - "test_shake": "Test shake", "thermal_adapter_attached_to_module": "The thermal adapter should be attached to the module.", "troubleshoot_step_1": "Return to Step 1 to see instructions for securing the module to the deck.", "troubleshoot_step_3": "Return to Step 3 to see instructions for securing the thermal adapter to the module.", diff --git a/app/src/assets/localization/en/incompatible_modules.json b/app/src/assets/localization/en/incompatible_modules.json index d9b1a231f0c..6829c971d24 100644 --- a/app/src/assets/localization/en/incompatible_modules.json +++ b/app/src/assets/localization/en/incompatible_modules.json @@ -1,7 +1,7 @@ { "incompatible_modules_attached": "incompatible module detected", - "remove_before_running_protocol": "Remove the following hardware before running a protocol:", + "is_not_compatible": "{{module_name}} is not compatible with the {{robot_type}}", "needs_your_assistance": "{{robot_name}} needs your assistance", - "remove_before_using": "You must remove incompatible modules before using this robot.", - "is_not_compatible": "{{module_name}} is not compatible with the {{robot_type}}" + "remove_before_running_protocol": "Remove the following hardware before running a protocol:", + "remove_before_using": "You must remove incompatible modules before using this robot." } diff --git a/app/src/assets/localization/en/labware_details.json b/app/src/assets/localization/en/labware_details.json index 3b25beffefc..ef1b786d666 100644 --- a/app/src/assets/localization/en/labware_details.json +++ b/app/src/assets/localization/en/labware_details.json @@ -8,8 +8,8 @@ "generic": "generic", "height": "height", "length": "length", - "manufacturer_number": "manufacturer / catalog #", "manufacturer": "manufacturer", + "manufacturer_number": "manufacturer / catalog #", "max_volume": "max volume", "measurements": "Measurements (mm)", "na": "n/a", @@ -21,8 +21,8 @@ "u": "U_Bottom", "v": "V_Bottom", "various": "various", - "well_count": "Well Count", "well": "Well", + "well_count": "Well Count", "width": "width", "x_offset": "x-offset", "x_size": "x-size", diff --git a/app/src/assets/localization/en/labware_landing.json b/app/src/assets/localization/en/labware_landing.json index 17eebda979d..3780788b4ee 100644 --- a/app/src/assets/localization/en/labware_landing.json +++ b/app/src/assets/localization/en/labware_landing.json @@ -3,20 +3,20 @@ "cancel": "cancel", "cannot-run-python-missing-labware": "Robots cannot run Python protocols with missing labware definitions.", "category": "Category", - "choose_file_to_upload": "Or choose a file from your computer to upload.", "choose_file": "Choose file", + "choose_file_to_upload": "Or choose a file from your computer to upload.", "copied": "Copied!", "create_new_def": "Create a new labware definition", "custom_def": "Custom Definition", "date_added": "Added", "def_moved_to_trash": "This labware definition will be moved to this computer’s trash and may be unrecoverable.", - "delete_this_labware": "Delete this labware definition?", "delete": "Delete", + "delete_this_labware": "Delete this labware definition?", "duplicate_labware_def": "Duplicate labware definition", "error_importing_file": "Error importing {{filename}}.", "go_to_def": "Go to labware definition", - "import_custom_def": "Import a Custom Labware Definition", "import": "Import", + "import_custom_def": "Import a Custom Labware Definition", "imported": "{{filename}} imported.", "invalid_labware_def": "Invalid labware definition", "labware": "labware", diff --git a/app/src/assets/localization/en/module_wizard_flows.json b/app/src/assets/localization/en/module_wizard_flows.json index 34e14017162..2ca733e2725 100644 --- a/app/src/assets/localization/en/module_wizard_flows.json +++ b/app/src/assets/localization/en/module_wizard_flows.json @@ -1,21 +1,21 @@ { "attach_probe": "Attach probe to pipette", "begin_calibration": "Begin calibration", - "calibrate_pipette": "Calibrate pipettes before proceeding to module calibration", "calibrate": "Calibrate", + "calibrate_pipette": "Calibrate pipettes before proceeding to module calibration", + "calibration": "{{module}} Calibration", "calibration_adapter_heatershaker": "Calibration Adapter", "calibration_adapter_temperature": "Calibration Adapter", "calibration_adapter_thermocycler": "Calibration Adapter", - "calibration_probe_touching_thermocycler": "The calibration probe will touch the sides of the calibration square in Thermocycler to determine its exact position", - "calibration_probe_touching": "The calibration probe will touch the sides of the calibration square in {{module}} in slot {{slotNumber}} to determine its exact position", "calibration_probe": "Take the calibration probe from its storage location. Ensure its collar is unlocked. Push the pipette ejector up and press the probe firmly onto the pipette nozzle. Twist the collar to lock the probe. Test that the probe is secure by gently pulling it back and forth.", - "calibration": "{{module}} Calibration", + "calibration_probe_touching": "The calibration probe will touch the sides of the calibration square in {{module}} in slot {{slotNumber}} to determine its exact position", + "calibration_probe_touching_thermocycler": "The calibration probe will touch the sides of the calibration square in Thermocycler to determine its exact position", "checking_firmware": "Checking {{module}} firmware", "complete_calibration": "Complete calibration", "confirm_location": "Confirm location", "confirm_placement": "Confirm placement", - "detach_probe_description": "Unlock the pipette calibration probe, remove it from the nozzle, and return it to its storage location.", "detach_probe": "Remove pipette probe", + "detach_probe_description": "Unlock the pipette calibration probe, remove it from the nozzle, and return it to its storage location.", "error_during_calibration": "Error during calibration", "error_prepping_module": "Error prepping module for calibration", "exit": "Exit", @@ -32,16 +32,16 @@ "move_gantry_to_front": "Move gantry to front", "next": "Next", "pipette_probe": "Pipette probe", + "place_flush": "Place the adapter flush on top of the module.", "place_flush_heater_shaker": "Place the adapter flush on the top of the module. Secure the adapter to the module with a thermal adapter screw and T10 Torx screwdriver.", "place_flush_thermocycler": "Ensure the Thermocycler lid is open and place the adapter flush on top of the module where the labware would normally go. ", - "place_flush": "Place the adapter flush on top of the module.", "prepping_module": "Prepping {{module}} for module calibration", "recalibrate": "Recalibrate", "select_location": "Select module location", "select_the_slot": "Select the slot where you installed the {{module}} on the deck map to the right. The location must be correct for successful calibration.", "slot_unavailable": "Slot unavailable", - "stand_back_robot_in_motion": "Stand back, robot is in motion", "stand_back": "Stand back, calibration in progress", + "stand_back_robot_in_motion": "Stand back, robot is in motion", "start_setup": "Start setup", "successfully_calibrated": "{{module}} successfully calibrated" } diff --git a/app/src/assets/localization/en/pipette_wizard_flows.json b/app/src/assets/localization/en/pipette_wizard_flows.json index 1154d6f9659..02b186d4026 100644 --- a/app/src/assets/localization/en/pipette_wizard_flows.json +++ b/app/src/assets/localization/en/pipette_wizard_flows.json @@ -2,14 +2,14 @@ "align_the_connector": "Attach the pipette to the robot by aligning the connector and pressing to ensure a secure connection. Hold the pipette in place and use the hex screwdriver to tighten the pipette screws. Then test that the pipette is securely attached by gently pulling it side to side.", "all_pipette_detached": "All pipettes successfully detached", "are_you_sure_exit": "Are you sure you want to exit before completing {{flow}}?", - "attach_96_channel_plus_detach": "Detach {{pipetteName}} and Attach 96-Channel Pipette", + "attach": "Attaching Pipette", "attach_96_channel": "Attach 96-Channel Pipette", - "attach_mounting_plate_instructions": "Attach the mounting plate by aligning the pins on the plate to the slots on the gantry carriage. You may need to adjust the position of the right pipette mount to achieve proper alignment.", + "attach_96_channel_plus_detach": "Detach {{pipetteName}} and Attach 96-Channel Pipette", "attach_mounting_plate": "Attach Mounting Plate", + "attach_mounting_plate_instructions": "Attach the mounting plate by aligning the pins on the plate to the slots on the gantry carriage. You may need to adjust the position of the right pipette mount to achieve proper alignment.", "attach_pip": "attach pipette", "attach_pipette": "attach {{mount}} pipette", "attach_probe": "attach calibration probe", - "attach": "Attaching Pipette", "backmost": "backmost", "before_you_begin": "Before you begin", "begin_calibration": "Begin calibration", @@ -25,6 +25,7 @@ "connect_and_secure_pipette": "connect and secure pipette", "continue": "Continue", "critical_unskippable_step": "this is a critical step that should not be skipped", + "detach": "Detaching Pipette", "detach_96_attach_mount": "Detach 96-Channel Pipette and Attach {{mount}} Pipette", "detach_96_channel": "Detach 96-Channel Pipette", "detach_and_reattach": "Detach and reattach pipette", @@ -32,14 +33,13 @@ "detach_mount_attach_96": "Detach {{mount}} Pipette and Attach 96-Channel Pipette", "detach_mounting_plate_instructions": "Hold onto the plate so it does not fall. Then remove the pins on the plate from the slots on the gantry carriage.", "detach_next_pipette": "Detach next pipette", - "detach_pipette_to_attach_96": "Detach {{pipetteName}} and Attach 96-Channel pipette", "detach_pipette": "detach {{mount}} pipette", + "detach_pipette_to_attach_96": "Detach {{pipetteName}} and Attach 96-Channel pipette", "detach_pipettes_attach_96": "Detach Pipettes and Attach 96-Channel Pipette", "detach_z_axis_screw_again": "detach the z-axis screw before attaching the 96-Channel Pipette.", - "detach": "Detaching Pipette", "exit_cal": "Exit calibration", - "firmware_updating": "A firmware update is required, instrument is updating...", "firmware_up_to_date": "No firmware update found.", + "firmware_updating": "A firmware update is required, instrument is updating...", "gantry_empty_for_96_channel_success": "Now that both mounts are empty, you can begin the 96-Channel Pipette attachment process.", "get_started_detach": "To get started, remove labware from the deck and clean up the working area to make detachment easier. Also gather the needed equipment shown to the right.", "grab_screwdriver": "While continuing to hold in place, grab your 2.5mm driver and tighten screws as shown in the animation. Test the pipette attachment by giving it a wiggle before pressing continue", @@ -71,8 +71,8 @@ "reattach_carriage": "reattach z-axis carriage", "recalibrate_pipette": "recalibrate {{mount}} pipette", "remove_cal_probe": "remove calibration probe", - "remove_labware_to_get_started": "To get started, remove labware from the deck and clean up the working area to make calibration easier. Also gather the needed equipment shown to the right.The calibration probe is included with the robot and should be stored on the front pillar of the robot.", "remove_labware": "To get started, remove labware from the deck and clean up the working area to make attachment and calibration easier. Also gather the needed equipment shown to the right.The calibration probe is included with the robot and should be stored on the front pillar of the robot.", + "remove_labware_to_get_started": "To get started, remove labware from the deck and clean up the working area to make calibration easier. Also gather the needed equipment shown to the right.The calibration probe is included with the robot and should be stored on the front pillar of the robot.", "remove_probe": "unlock the calibration probe, remove it from the nozzle, and return it to its storage location.", "replace_pipette": "replace {{mount}} pipette", "return_probe_error": "Return the calibration probe to its storage location before exiting. {{error}}", diff --git a/app/src/assets/localization/en/protocol_command_text.json b/app/src/assets/localization/en/protocol_command_text.json index fa7484e8c88..9dc4f0321ac 100644 --- a/app/src/assets/localization/en/protocol_command_text.json +++ b/app/src/assets/localization/en/protocol_command_text.json @@ -61,16 +61,18 @@ "offdeck": "offdeck", "on_location": "on {{location}}", "opening_tc_lid": "Opening Thermocycler lid", + "partial_layout": "partial layout", "pause": "Pause", "pause_on": "Pause on {{robot_name}}", - "partial_layout": "partial layout", "pickup_tip": "Picking up tip(s) from {{well_range}} of {{labware}} in {{labware_location}}", "prepare_to_aspirate": "Preparing {{pipette}} to aspirate", + "pressurizing_to_dispense": "Pressurize pipette to dispense {{volume}} µL from resin tip at {{flow_rate}} µL/sec", "reloading_labware": "Reloading {{labware}}", "return_tip": "Returning tip to {{well_name}} of {{labware}} in {{labware_location}}", "right": "Right", "row_layout": "row layout", "save_position": "Saving position", + "sealing_to_location": "Sealing to {{labware}} in {{location}}", "set_and_await_hs_shake": "Setting Heater-Shaker to shake at {{rpm}} rpm and waiting until reached", "setting_hs_temp": "Setting Target Temperature of Heater-Shaker to {{temp}}", "setting_temperature_module_temp": "Setting Temperature Module to {{temp}} (rounded to nearest integer)", @@ -91,6 +93,7 @@ "turning_rail_lights_off": "Turning rail lights off", "turning_rail_lights_on": "Turning rail lights on", "unlatching_hs_latch": "Unlatching labware on Heater-Shaker", + "unsealing_from_location": "Unsealing from {{labware}} in {{location}}", "wait_for_duration": "Pausing for {{seconds}} seconds. {{message}}", "wait_for_resume": "Pausing protocol", "waiting_for_hs_to_reach": "Waiting for Heater-Shaker to reach target temperature", diff --git a/app/src/assets/localization/en/protocol_details.json b/app/src/assets/localization/en/protocol_details.json index b93e675a1c5..53531f1e00a 100644 --- a/app/src/assets/localization/en/protocol_details.json +++ b/app/src/assets/localization/en/protocol_details.json @@ -10,31 +10,32 @@ "connected": "connected", "connection_status": "connection status", "creation_method": "creation method", - "csv_file_type_required": "CSV file type required", "csv_file": "CSV file", + "csv_file_type_required": "CSV file type required", + "deck": "deck", "deck_view": "Deck View", "default_value": "Default Value", - "delete_protocol_perm": "{{name}} and its run history will be permanently deleted.", "delete_protocol": "Delete Protocol", + "delete_protocol_perm": "{{name}} and its run history will be permanently deleted.", "delete_this_protocol": "Delete this protocol?", "description": "description", "extension_mount": "extension mount", "file_required": "File required", "go_to_labware_definition": "Go to labware definition", "go_to_timeline": "Go to timeline", - "gripper_pick_up_count_description": "individual move labware commands that use the gripper.", "gripper_pick_up_count": "Grip Count", + "gripper_pick_up_count_description": "individual move labware commands that use the gripper.", "hardware": "hardware", - "labware_name": "Labware name", "labware": "labware", + "labware_name": "Labware name", "last_analyzed": "last analyzed", "last_updated": "last updated", "left_and_right_mounts": "left + right mounts", "left_mount": "left mount", "left_right": "Left, Right", "liquid_name": "liquid name", - "liquids_not_in_protocol": "no liquids are specified for this protocol", "liquids": "liquids", + "liquids_not_in_protocol": "no liquids are specified for this protocol", "listed_values_are_view_only": "Listed values are view-only", "location": "location", "modules": "modules", @@ -50,16 +51,16 @@ "num_choices": "{{num}} choices", "num_options": "{{num}} options", "off": "Off", - "on_off": "On, off", "on": "On", + "on_off": "On, off", "org_or_author": "org/author", "parameters": "Parameters", - "pipette_aspirate_count_description": "individual aspirate commands per pipette.", "pipette_aspirate_count": "{{pipette}} aspirate count", - "pipette_dispense_count_description": "individual dispense commands per pipette.", + "pipette_aspirate_count_description": "individual aspirate commands per pipette.", "pipette_dispense_count": "{{pipette}} dispense count", - "pipette_pick_up_count_description": "individual pick up tip commands per pipette.", + "pipette_dispense_count_description": "individual dispense commands per pipette.", "pipette_pick_up_count": "{{pipette}} pick up tip count", + "pipette_pick_up_count_description": "individual pick up tip commands per pipette.", "proceed_to_setup": "Proceed to setup", "protocol_designer_version": "Protocol Designer {{version}}", "protocol_failed_app_analysis": "This protocol failed in-app analysis. It may be unusable on robots without custom software configurations.", @@ -73,24 +74,25 @@ "requires_upload": "Requires upload", "restore_defaults": "Restore default values", "right_mount": "right mount", + "robot": "robot", "robot_configuration": "robot configuration", - "robot_is_busy_with_protocol": "{{robotName}} is busy with {{protocolName}} in {{runStatus}} state. Do you want to clear it and proceed?", "robot_is_busy": "{{robotName}} is busy", - "robot": "robot", + "robot_is_busy_with_protocol": "{{robotName}} is busy with {{protocolName}} in {{runStatus}} state. Do you want to clear it and proceed?", "run_protocol": "Run protocol", "select_parameters_for_robot": "Select parameters for {{robot_name}}", "send": "Send", "sending": "Sending", "show_in_folder": "Show in folder", "slot": "Slot {{slotName}}", - "start_setup_customize_values": "Start setup to customize values", "start_setup": "Start setup", + "start_setup_customize_values": "Start setup to customize values", "successfully_sent": "Successfully sent", + "summary": "Summary", "total_volume": "total volume", - "unavailable_or_busy_robot_not_listed_plural": "{{count}} unavailable or busy robots are not listed.", "unavailable_or_busy_robot_not_listed": "{{count}} unavailable or busy robot is not listed.", - "unavailable_robot_not_listed_plural": "{{count}} unavailable robots are not listed.", + "unavailable_or_busy_robot_not_listed_plural": "{{count}} unavailable or busy robots are not listed.", "unavailable_robot_not_listed": "{{count}} unavailable robot is not listed.", + "unavailable_robot_not_listed_plural": "{{count}} unavailable robots are not listed.", "unsuccessfully_sent": "Unsuccessfully sent", "value_out_of_range": "Value must be between {{min}}-{{max}}", "view_run_details": "View run details", diff --git a/app/src/assets/localization/en/protocol_info.json b/app/src/assets/localization/en/protocol_info.json index 66c2fc9aa89..9278d55361e 100644 --- a/app/src/assets/localization/en/protocol_info.json +++ b/app/src/assets/localization/en/protocol_info.json @@ -23,9 +23,9 @@ "exit_modal_heading": "Confirm Close Protocol", "failed_analysis": "failed analysis", "get_labware_offset_data": "Get Labware Offset Data", + "import": "Import", "import_a_file": "Import a protocol to get started", "import_new_protocol": "Import a Protocol", - "import": "Import", "incompatible_file_type": "Incompatible file type", "instrument_cal_data_title": "Calibration data", "instrument_not_attached": "Not attached", @@ -38,8 +38,8 @@ "labware_offset_data_title": "Labware Offset data", "labware_offsets_info": "{{number}} Labware Offsets", "labware_position_check_complete_toast_no_offsets": "Labware Position Check complete. No Labware Offsets created.", - "labware_position_check_complete_toast_with_offsets_plural": "Labware Position Check complete. {{count}} Labware Offsets created.", "labware_position_check_complete_toast_with_offsets": "Labware Position Check complete. {{count}} Labware Offset created.", + "labware_position_check_complete_toast_with_offsets_plural": "Labware Position Check complete. {{count}} Labware Offsets created.", "labware_title": "Required Labware", "last_run": "Last Run", "last_run_time": "Last run {{time}}", @@ -83,7 +83,7 @@ "unpin_protocol": "Unpin protocol", "unpinned_protocol": "Unpinned protocol", "update_robot_for_custom_labware": "You have custom labware definitions saved to your app, but this robot needs to be updated before you can use these definitions with Python protocols", - "upload_and_simulate": "Open a protocol to run on {{robot_name}}", "upload": "Upload", + "upload_and_simulate": "Open a protocol to run on {{robot_name}}", "valid_file_types": "Valid file types: Python files (.py) or Protocol Designer files (.json)" } diff --git a/app/src/assets/localization/en/protocol_list.json b/app/src/assets/localization/en/protocol_list.json index d70d8e6e7b7..bfc177829c5 100644 --- a/app/src/assets/localization/en/protocol_list.json +++ b/app/src/assets/localization/en/protocol_list.json @@ -16,8 +16,8 @@ "reanalyze_to_view": "Reanalyze protocol", "right_mount": "right mount", "robot": "robot", - "send_to_robot_overflow": "Send to {{robot_display_name}}", "send_to_robot": "Send protocol to {{robot_display_name}}", + "send_to_robot_overflow": "Send to {{robot_display_name}}", "show_in_folder": "Show in folder", "start_setup": "Start setup", "this_protocol_will_be_trashed": "This protocol will be moved to this computer’s trash and may be unrecoverable.", diff --git a/app/src/assets/localization/en/protocol_setup.json b/app/src/assets/localization/en/protocol_setup.json index 17f60958d55..d740eec25a1 100644 --- a/app/src/assets/localization/en/protocol_setup.json +++ b/app/src/assets/localization/en/protocol_setup.json @@ -263,8 +263,8 @@ "restore_defaults": "Restore default values", "robot_cal_description": "Robot calibration establishes how the robot knows where it is in relation to the deck. Accurate Robot calibration is essential to run protocols successfully. Robot calibration has 3 parts: Deck calibration, Tip Length calibration and Pipette Offset calibration.", "robot_cal_help_title": "How Robot Calibration Works", - "robot_calibration_step_description_pipettes_only": "Review required instruments and calibrations for this protocol.", "robot_calibration_step_description": "Review required pipettes and tip length calibrations for this protocol.", + "robot_calibration_step_description_pipettes_only": "Review required instruments and calibrations for this protocol.", "robot_calibration_step_ready": "Calibration ready", "robot_calibration_step_title": "Instruments", "run": "Run", diff --git a/app/src/assets/localization/en/quick_transfer.json b/app/src/assets/localization/en/quick_transfer.json index c448de06a72..cb63412c3c4 100644 --- a/app/src/assets/localization/en/quick_transfer.json +++ b/app/src/assets/localization/en/quick_transfer.json @@ -37,6 +37,7 @@ "consolidate_volume_error": "The selected destination well is too small to consolidate into. Try consolidating from fewer wells.", "create_new_to_edit": "Create a new quick transfer to edit", "create_new_transfer": "Create new quick transfer", + "create_to_get_started": "Create a new quick transfer to get started.", "create_transfer": "Create transfer", "delay": "Delay", "delay_after_aspirating": "Delay after aspirating", @@ -44,7 +45,6 @@ "delay_duration_s": "Delay duration (seconds)", "delay_position_mm": "Delay position from bottom of well (mm)", "delay_value": "{{delay}}s, {{position}} mm from bottom", - "create_to_get_started": "Create a new quick transfer to get started.", "delete_this_transfer": "Delete this quick transfer?", "delete_transfer": "Delete quick transfer", "deleted_transfer": "Deleted quick transfer", @@ -63,8 +63,8 @@ "enter_characters": "Enter up to 60 characters", "error_analyzing": "An error occurred while attempting to analyze {{transferName}}.", "exit_quick_transfer": "Exit quick transfer?", - "flow_rate_value": "{{flow_rate}} µL/s", "failed_analysis": "failed analysis", + "flow_rate_value": "{{flow_rate}} µL/s", "got_it": "Got it", "grid": "grid", "grids": "grids", @@ -104,8 +104,8 @@ "reservoir": "Reservoirs", "right_mount": "Right Mount", "run_now": "Run now", - "run_transfer": "Run quick transfer", "run_quick_transfer_now": "Do you want to run your quick transfer now?", + "run_transfer": "Run quick transfer", "save": "Save", "save_for_later": "Save for later", "save_to_run_later": "Save your quick transfer to run it in the future.", @@ -129,15 +129,13 @@ "tip_position": "Tip position", "tip_position_value": "{{position}} mm from the bottom", "tip_rack": "Tip rack", + "too_many_pins_body": "Remove a quick transfer in order to add more transfers to your pinned list.", + "too_many_pins_header": "You've hit your max!", "touch_tip": "Touch tip", "touch_tip_after_aspirating": "Touch tip after aspirating", "touch_tip_before_dispensing": "Touch tip before dispensing", "touch_tip_position_mm": "Touch tip position from top of well (mm)", "touch_tip_value": "{{position}} mm from bottom", - "use_deck_slots": "Quick transfers use deck slots B2-D2. These slots hold a tip rack, a source labware, and a destination labware.Make sure that your deck configuration is up to date to avoid collisions.", - "value_out_of_range": "Value must be between {{min}} to {{max}}", - "too_many_pins_body": "Remove a quick transfer in order to add more transfers to your pinned list.", - "too_many_pins_header": "You've hit your max!", "transfer_analysis_failed": "quick transfer analysis failed", "transfer_name": "Transfer Name", "trashBin": "Trash bin", @@ -145,6 +143,8 @@ "tubeRack": "Tube racks", "unpin_transfer": "Unpin quick transfer", "unpinned_transfer": "Unpinned quick transfer", + "use_deck_slots": "Quick transfers use deck slots B2-D2. These slots hold a tip rack, a source labware, and a destination labware.Make sure that your deck configuration is up to date to avoid collisions.", + "value_out_of_range": "Value must be between {{min}} to {{max}}", "volume_per_well": "Volume per well", "volume_per_well_µL": "Volume per well (µL)", "wasteChute": "Waste chute", diff --git a/app/src/assets/localization/en/shared.json b/app/src/assets/localization/en/shared.json index f4e542e761b..6ea0f44ab7a 100644 --- a/app/src/assets/localization/en/shared.json +++ b/app/src/assets/localization/en/shared.json @@ -11,8 +11,8 @@ "change_robot": "Change robot", "clear_data": "clear data", "close": "close", - "closed": "closed", "close_robot_door": "Close the robot door before starting the run.", + "closed": "closed", "confirm": "Confirm", "confirm_placement": "Confirm placement", "confirm_position": "Confirm position", diff --git a/app/src/assets/localization/en/top_navigation.json b/app/src/assets/localization/en/top_navigation.json index 16d5e2d011d..c3391804a59 100644 --- a/app/src/assets/localization/en/top_navigation.json +++ b/app/src/assets/localization/en/top_navigation.json @@ -9,8 +9,8 @@ "instruments": "Instruments", "labware": "Labware", "modules": "modules", - "pipettes_not_calibrated": "Please calibrate all pipettes specified in loaded protocol to proceed", "pipettes": "pipettes", + "pipettes_not_calibrated": "Please calibrate all pipettes specified in loaded protocol to proceed", "please_connect_to_a_robot": "Please connect to a robot to proceed", "please_load_a_protocol": "Please load a protocol to proceed", "protocol_details": "Protocol Details", diff --git a/app/src/assets/localization/zh/anonymous.json b/app/src/assets/localization/zh/anonymous.json index 045245c84f7..7abd8f08615 100644 --- a/app/src/assets/localization/zh/anonymous.json +++ b/app/src/assets/localization/zh/anonymous.json @@ -1,9 +1,9 @@ { - "a_robot_software_update_is_available": "需要更新工作站软件版本才能使用该版本的桌面应用程序运行协议。转到工作站转到工作站", "about_flex_gripper": "关于转板抓手", "alternative_security_types_description": "工作站支持连接到各种企业接入点。通过USB连接并在桌面应用程序中完成设置。", - "attach_a_pipette_for_quick_transfer": "为创建快速移液,您需要在工作站上安装移液器。", "attach_a_pipette": "将移液器连接到工作站", + "attach_a_pipette_for_quick_transfer": "为创建快速移液,您需要在工作站上安装移液器。", "calibration_block_description": "这个金属块是一个特制的工具,完美适配您的甲板,有助于校准。如果您没有校准块,请发送电子邮件给支持团队,以便我们寄送一个给您。在您提供的信息中,请确保包括您的姓名、公司或机构名称和寄送地址。在等待校准块到达过程中,您可以暂时利用工作站里垃圾桶上的平面进行校准。", "calibration_on_opentrons_tips_is_important": "使用上述吸头和吸头盒进行校准非常重要,因为工作站的准确性是基于这些吸头的已知尺寸来确定的。", "choose_what_data_to_share": "选择要共享的工作站数据。", @@ -23,13 +23,14 @@ "find_your_robot": "在应用程序的“设备”栏找到您的工作站,以安装软件更新。", "firmware_update_download_logs": "请与支持人员联系以获得帮助。", "general_error_message": "如果该消息反复出现,请尝试重新启动您的应用程序和工作站。如果这不能解决问题,请与支持人员联系。", + "gripper": "转板抓手", "gripper_still_attached": "转板抓手仍处于连接状态", "gripper_successfully_attached_and_calibrated": "转板抓手已成功连接并校准", "gripper_successfully_calibrated": "转板抓手已成功校准", "gripper_successfully_detached": "转板抓手已成功卸下", - "gripper": "转板抓手", "help_us_improve_send_error_report": "通过向支持团队发送错误报告,帮助我们改进您的使用体验", "ip_description_second": "请联系网络管理员,为工作站分配静态IP地址。", + "language_preference_description": "除非您在下面选择其他语言,否则应用将与您的系统语言匹配。您可以稍后在应用设置中更改语言。", "learn_uninstalling": "了解更多有关卸载应用程序的信息", "loosen_screws_and_detach": "松开螺丝并卸下转板抓手", "modal_instructions": "有关设置模块的分步说明,请参阅随包装附带的快速指引。", @@ -48,8 +49,8 @@ "opentrons_def": "已验证的数据", "opentrons_flex_quickstart_guide": "快速入门指南", "opentrons_labware_def": "已验证的实验耗材数据", - "opentrons_tip_racks_recommended": "建议使用Opentrons吸头盒。其他吸头盒无法保证精度。", "opentrons_tip_rack_name": "opentrons", + "opentrons_tip_racks_recommended": "建议使用Opentrons吸头盒。其他吸头盒无法保证精度。", "previous_releases": "查看以前的版本", "receive_alert": "当软件更新可用时接收提醒。", "restore_description": "不建议恢复到过往的软件版本,但您可以访问下方的过往版本。为了获得最佳效果,请在安装过往版本之前卸载现有应用程序并删除其配置文件。", @@ -68,7 +69,10 @@ "show_labware_offset_snippets_description": "仅适用于需要在应用程序之外应用耗材校准数据的用户。启用后,在设置协议过程中可访问Jupyter Notebook和SSH的代码片段。", "something_seems_wrong": "您的移液器可能有问题。退出设置并联系支持人员以获取帮助。", "storage_limit_reached_description": "您的工作站已达到可存储的快速移液数量上限。在创建新的快速移液之前,您必须删除一个现有的快速移液。", + "system_language_preferences_update_description": "您系统的语言最近已更新。您想使用更新后的语言作为应用的默认语言吗?", "these_are_advanced_settings": "这些是高级设置。请勿在没有支持团队帮助的情况下尝试调整这些设置。更改这些设置可能会影响您的移液器寿命。这些设置不会覆盖协议中定义的任何移液器设置。", + "u2e_driver_description": "OT-2 通过此适配器,使用 USB 连接 Opentrons APP。", + "unexpected_error": "发生意外错误。", "update_requires_restarting_app": "更新需要重新启动应用程序。", "update_robot_software_description": "绕过自动更新过程并手动更新工作站软件", "update_robot_software_link": "启动软件更新页面", diff --git a/app/src/assets/localization/zh/app_settings.json b/app/src/assets/localization/zh/app_settings.json index ace4ca5fb4f..b84f0c5b1e8 100644 --- a/app/src/assets/localization/zh/app_settings.json +++ b/app/src/assets/localization/zh/app_settings.json @@ -1,9 +1,12 @@ { "__dev_internal__enableLabwareCreator": "启用应用实验耗材创建器", - "__dev_internal__forceHttpPolling": "强制轮询所有网络请求,而不是使用MQTT", "__dev_internal__enableRunNotes": "在协议运行期间显示备注", + "__dev_internal__forceHttpPolling": "强制轮询所有网络请求,而不是使用MQTT", + "__dev_internal__lpcRedesign": "LPC 重新设计", "__dev_internal__protocolStats": "协议统计", "__dev_internal__protocolTimeline": "协议时间线", + "__dev_internal__reactQueryDevtools": "启用开发者工具", + "__dev_internal__reactScan": "启用 React 组件扫描", "add_folder_button": "添加实验耗材源文件夹", "add_ip_button": "添加", "add_ip_error": "输入IP地址或主机名", @@ -14,11 +17,14 @@ "additional_labware_folder_title": "其他定制实验耗材源文件夹", "advanced": "高级", "app_changes": "应用程序更改于", + "app_language_description": "应用的所有功能界面将使用所选语言显示,但协议和用户生成的内容(如文本或文件)将保持原有语言,不会随语言设置而改变。", + "app_language_preferences": "应用程序语言偏好设置", "app_settings": "应用设置", "bug_fixes": "错误修复", "cal_block": "始终使用校准块进行校准", "change_folder_button": "更改实验耗材源文件夹", "channel": "通道", + "choose_your_language": "选择语言", "clear_confirm": "清除不可用的工作站", "clear_robots_button": "清除不可用工作站列表", "clear_robots_description": "清除设备页面上不可用工作站的列表。此操作无法撤消。", @@ -30,19 +36,27 @@ "connect_ip_button": "完成", "connect_ip_link": "了解更多关于手动连接工作站的信息", "discovery_timeout": "发现超时。", + "dont_change": "不改变", + "dont_remind_me": "不需要再次提醒", "download_update": "正在下载更新...", + "driver_out_of_date": "网卡驱动程序更新可用", "enable_dev_tools": "开发者工具", "enable_dev_tools_description": "启用此设置将在应用启动时打开开发者工具,打开额外的日志记录并访问功能标志。", "error_boundary_desktop_app_description": "您需要重新加载应用程序。出现以下错误信息,请联系技术支持:", "error_boundary_title": "发生未知错误", + "error_recovery_mode": "恢复模式", + "error_recovery_mode_description": "出现协议错误时暂停,而不是取消运行。", "feature_flags": "功能标志", "general": "通用", + "get_update": "获取更新", "heater_shaker_attach_description": "在进行测试振荡功能或在协议中使用热震荡模块功能之前,显示正确连接热震荡模块的提醒。", "heater_shaker_attach_visible": "确认热震荡模块连接", "how_to_restore": "如何恢复过往的软件版本", "installing_update": "正在安装更新...", "ip_available": "可用", "ip_description_first": "输入IP地址或主机名以连接到工作站。", + "language": "语言 (Language)", + "language_preference": "语言偏好", "manage_versions": "工作站版本和应用程序软件版本必须一致。通过工作站设置 > 高级查看工作站软件版本。", "new_features": "新功能", "no_folder": "未指定其他源文件夹", @@ -55,6 +69,7 @@ "ot2_advanced_settings": "OT-2高级设置", "override_path": "覆盖路径", "override_path_to_python": "覆盖Python路径", + "please_update_driver": "请更新您的计算机的驱动程序以确保与 OT-2 稳定连接。", "prevent_robot_caching": "阻止工作站进行缓存", "prevent_robot_caching_description": "启用此功能后,应用程序将立即清除不可用的工作站,并且不会记住它们。在网络上有许多工作站的情况下,防止缓存可能会提高网络性能,但代价是在应用程序启动时工作站发现的速度变慢且可靠性降低。", "privacy": "隐私", @@ -68,6 +83,8 @@ "restarting_app": "下载完成,正在重启应用程序...", "restore_previous": "查看如何恢复过往软件版本", "searching": "正在搜索30秒", + "select_a_language": "请选择使用语言。", + "select_language": "选择语言 (Select language)", "setup_connection": "设置连接", "share_display_usage": "分享屏幕使用情况", "share_robot_logs": "分享工作站日志", @@ -76,10 +93,12 @@ "software_update_available": "有可用的软件更新", "software_version": "应用程序软件版本", "successfully_deleted_unavail_robots": "成功删除不可用的工作站", + "system_language_preferences_update": "更新您的系统语言偏好设置", "tip_length_cal_method": "吸头长度校准方法", "trash_bin": "始终使用垃圾桶进行校准", "try_restarting_the_update": "尝试重新启动更新。", "turn_off_updates": "在应用程序设置中关闭软件更新通知。", + "u2e_driver_outdated_message": "您的计算机有可用的网卡驱动程序更新。", "up_to_date": "最新", "update_alerts": "软件更新提醒", "update_app_now": "立即更新应用程序", @@ -97,6 +116,8 @@ "usb_to_ethernet_not_connected": "没有连接USB-to-Ethernet适配器", "usb_to_ethernet_unknown_manufacturer": "未知制造商", "usb_to_ethernet_unknown_product": "未知适配器", + "use_system_language": "使用系统语言", + "view_adapter_info": "查看适配器信息", "view_software_update": "查看软件更新", "view_update": "查看更新" } diff --git a/app/src/assets/localization/zh/branded.json b/app/src/assets/localization/zh/branded.json index c38888398f1..b7cbc41d684 100644 --- a/app/src/assets/localization/zh/branded.json +++ b/app/src/assets/localization/zh/branded.json @@ -2,8 +2,8 @@ "a_robot_software_update_is_available": "需要更新工作站软件才能使用此版本的Opentrons应用程序运行协议。转到工作站", "about_flex_gripper": "关于Flex转板抓手", "alternative_security_types_description": "Opentrons应用程序支持将Flex连接到各种企业接入点。通过USB连接并在应用程序中完成设置。", - "attach_a_pipette_for_quick_transfer": "要创建快速移液,您需要将移液器安装到您的Opentrons Flex上。", "attach_a_pipette": "将移液器连接到Flex", + "attach_a_pipette_for_quick_transfer": "要创建快速移液,您需要将移液器安装到您的Opentrons Flex上。", "calibration_block_description": "这个金属块是一个特制的工具,完美适配您的甲板,有助于校准。如果您没有校准块,请发送电子邮件至support@opentrons.com,以便我们寄送一个给您。在您提供的信息中,请确保包括您的姓名、公司或机构名称和寄送地址。在等待校准块到达过程中,您可以暂时利用工作站里垃圾桶上的平面进行校准。", "calibration_on_opentrons_tips_is_important": "使用上述Opentrons吸头和吸头盒进行校准非常重要,因为工作站的准确性是基于这些吸头的已知尺寸来确定的。", "choose_what_data_to_share": "选择要与Opentrons共享的数据。", @@ -23,13 +23,14 @@ "find_your_robot": "在Opentrons应用程序中找到您的工作站以安装软件更新。", "firmware_update_download_logs": "从Opentrons应用程序下载工作站日志并将其发送到support@opentrons.com寻求帮助。", "general_error_message": "如果您一直收到此消息,请尝试重新启动您的应用程序和工作站。如果这不能解决问题,请与Opentrons支持人员联系。", + "gripper": "Flex转板抓手", "gripper_still_attached": "Flex转板抓手仍处于连接状态", "gripper_successfully_attached_and_calibrated": "Flex转板抓手已成功连接并校准", "gripper_successfully_calibrated": "Flex转板抓手已成功校准", "gripper_successfully_detached": "Flex转板抓手已成功卸下", - "gripper": "Flex转板抓手", "help_us_improve_send_error_report": "通过向{{support_email}}发送错误报告,帮助我们改进您的使用体验", "ip_description_second": "Opentrons建议您联系网络管理员,为工作站分配静态IP地址。", + "language_preference_description": "Opentrons APP默认匹配与您的系统语言,您也可以选择使用下方其他语言。当然,后续您也可以在APP设置中进行语言更改。", "learn_uninstalling": "了解更多有关卸载Opentrons应用程序的信息", "loosen_screws_and_detach": "松开螺丝并卸下Flex转板抓手", "modal_instructions": "有关设置模块的分步说明,请参阅随包装附带的快速指引。您也可以单击下面的链接或扫描二维码访问Opentrons帮助中心的模块部分。", @@ -68,7 +69,10 @@ "show_labware_offset_snippets_description": "仅适用于需要在Opentrons应用程序之外应用耗材校准数据的用户。启用后,在设置协议过程中可访问Jupyter Notebook和SSH的代码片段。", "something_seems_wrong": "您的移液器可能有问题。退出设置并联系Opentrons支持人员以获取帮助。", "storage_limit_reached_description": "您的 Opentrons Flex 已达到可存储的快速移液数量上限。在创建新的快速移液之前,您必须删除一个现有的快速移液。", + "system_language_preferences_update_description": "您的系统语言最近已更新。您想将更新后的语言用作 Opentrons APP的默认语言吗?", "these_are_advanced_settings": "这些是高级设置。请勿在没有Opentrons支持团队帮助的情况下尝试调整这些设置。更改这些设置可能会影响您的移液器寿命。这些设置不会覆盖协议中定义的任何移液器设置。", + "u2e_driver_description": "OT-2 通过此适配器,使用 USB 连接 Opentrons APP。", + "unexpected_error": "发生意外错误。如果问题仍然存在,请联系 Opentrons 支持团队寻求帮助。", "update_requires_restarting_app": "更新需要重新启动Opentrons应用程序。", "update_robot_software_description": "绕过Opentrons应用程序自动更新过程并手动更新工作站软件", "update_robot_software_link": "启动Opentrons软件更新页面", diff --git a/app/src/assets/localization/zh/change_pipette.json b/app/src/assets/localization/zh/change_pipette.json index 9818fd56f85..3a7f16bb724 100644 --- a/app/src/assets/localization/zh/change_pipette.json +++ b/app/src/assets/localization/zh/change_pipette.json @@ -1,8 +1,8 @@ { "are_you_sure_exit": "您确定要在{{direction}}移液器之前退出吗?", "attach_name_pipette": "安装一个{{pipette}}移液器", - "attach_pipette_type": "安装一个{{pipetteName}}移液器", "attach_pipette": "安装一个移液器", + "attach_pipette_type": "安装一个{{pipetteName}}移液器", "attach_the_pipette": "

连接移液器

推入白色连接器,直到感觉它插入移液器。", "attached_pipette_does_not_match": "连接的{{name}}与您最初选择的{{pipette}}不匹配。", "attaching": "正在连接", @@ -16,10 +16,10 @@ "confirming_attachment": "正在确认连接", "confirming_detachment": "正在确认拆卸", "continue": "继续", - "detach_pipette_from_mount": "从{{mount}}安装支架上卸下移液器", + "detach": "卸下移液器", "detach_pipette": "从{{mount}}安装支架上卸下{{pipette}}", + "detach_pipette_from_mount": "从{{mount}}安装支架上卸下移液器", "detach_try_again": "卸下并重试", - "detach": "卸下移液器", "detaching": "正在卸下", "get_started": "开始", "go_back": "返回", diff --git a/app/src/assets/localization/zh/device_details.json b/app/src/assets/localization/zh/device_details.json index a19e61a365b..fdcab146c28 100644 --- a/app/src/assets/localization/zh/device_details.json +++ b/app/src/assets/localization/zh/device_details.json @@ -1,15 +1,16 @@ { "about_gripper": "关于转板抓手", "about_module": "关于{{name}}", - "about_pipette_name": "关于{{name}}移液器", "about_pipette": "关于移液器", + "about_pipette_name": "关于{{name}}移液器", + "abs_reader_lid_status": "上盖状态: {{status}}", "abs_reader_status": "吸光度读板器状态", + "add": "添加", "add_fixture_description": "将此硬件添加至甲板配置。它在协议分析期间将会被引用。", "add_to_slot": "添加到板位{{slotName}}", - "add": "添加", + "an_error_occurred_while_updating": "更新移液器设置时发生错误。", "an_error_occurred_while_updating_module": "更新{{moduleName}}时出现错误,请重试。", "an_error_occurred_while_updating_please_try_again": "更新移液器设置时出错,请重试。", - "an_error_occurred_while_updating": "更新移液器设置时发生错误。", "attach_gripper": "安装转板抓手", "attach_pipette": "安装移液器", "bad_run": "无法加载运行", @@ -17,13 +18,13 @@ "bundle_firmware_file_not_found": "未找到类型为{{module}}的模块固件包文件。", "calibrate_gripper": "校准转板抓手", "calibrate_now": "立即校准", - "calibrate_pipette_offset": "校准移液器数据", "calibrate_pipette": "校准移液器", - "calibration_needed_without_link": "需要校准。", + "calibrate_pipette_offset": "校准移液器数据", "calibration_needed": "需要校准。 立即校准", + "calibration_needed_without_link": "需要校准。", "canceled": "已取消", - "changes_will_be_lost_description": "确定不保存甲板配置直接退出而吗?", "changes_will_be_lost": "更改将丢失", + "changes_will_be_lost_description": "确定不保存甲板配置直接退出而吗?", "choose_protocol_to_run": "选择在{{name}}上运行的协议", "close_lid": "关闭上盖", "completed": "已完成", @@ -35,9 +36,9 @@ "current_temp": "当前:{{temp}}°C", "current_version": "当前版本", "deck_cal_missing": "缺少移液器校准数据,请先校准甲板。", + "deck_configuration": "甲板配置", "deck_configuration_is_not_available_when_robot_is_busy": "工作站忙碌时,甲板配置不可用", "deck_configuration_is_not_available_when_run_is_in_progress": "工作站运行时,甲板配置不可用", - "deck_configuration": "甲板配置", "deck_fixture_setup_instructions": "甲板配置安装说明", "deck_fixture_setup_modal_bottom_description_desktop": "针对不同类型的配置,扫描二维码或访问下方链接获取详细说明。", "deck_fixture_setup_modal_top_description": "首先,拧松并移除计划安装模组的甲板。然后放置模组,并进行固定。", @@ -57,14 +58,14 @@ "estop_pressed": "急停按钮被按下。工作站运动已停止。", "failed": "失败", "files": "文件", - "firmware_update_needed": "需要更新工作站固件。请在工作站的触摸屏上开始更新。", "firmware_update_available": "固件更新可用。", "firmware_update_failed": "未能更新模块固件", - "firmware_updated_successfully": "固件更新成功", + "firmware_update_needed": "需要更新工作站固件。请在工作站的触摸屏上开始更新。", "firmware_update_occurring": "固件更新正在进行中...", + "firmware_updated_successfully": "固件更新成功", "fixture": "配置模组", - "have_not_run_description": "运行一些协议后,它们会在这里显示。", "have_not_run": "无最近运行记录", + "have_not_run_description": "运行一些协议后,它们会在这里显示。", "heater": "加热器", "height_ranges": "{{gen}}高度范围", "hot_to_the_touch": "模块接触时很热", @@ -73,12 +74,12 @@ "instruments_and_modules": "设备与模块", "labware_bottom": "耗材底部", "last_run_time": "最后一次运行{{number}}", - "left_right": "左右支架", "left": "左侧", + "left_right": "左右支架", "lights": "灯光", "link_firmware_update": "查看固件更新", - "location_conflicts": "位置冲突", "location": "位置", + "location_conflicts": "位置冲突", "magdeck_gen1_height": "高度:{{height}}", "magdeck_gen2_height": "高度:{{height}}毫米", "max_engage_height": "最大可用高度", @@ -87,13 +88,13 @@ "missing_hardware": "缺少硬件", "missing_instrument": "缺少{{num}}个设备", "missing_instruments_plural": "缺少{{count}}个设备", - "missing_module_plural": "缺少{{count}}个模块", "missing_module": "缺少{{num}}个模块", + "missing_module_plural": "缺少{{count}}个模块", "module_actions_unavailable": "协议运行时模块操作不可用", + "module_calibration_required": "需要模块校准。", "module_calibration_required_no_pipette_attached": "需要模块校准。在运行模块校准前,请连接移液器。", "module_calibration_required_no_pipette_calibrated": "需要模块校准。在校准模块前,请先校准移液器。", "module_calibration_required_update_pipette_FW": "在进行必要的模块校准前,请先更新移液器固件。", - "module_calibration_required": "需要模块校准。", "module_controls": "模块控制", "module_error": "模块错误", "module_name_error": "{{moduleName}}错误", @@ -104,8 +105,8 @@ "no_deck_fixtures": "无甲板配置", "no_protocol_runs": "暂无协议运行记录!", "no_protocols_found": "未找到协议", - "no_recent_runs_description": "运行一些协议后,它们将显示在此处。", "no_recent_runs": "无最近运行记录", + "no_recent_runs_description": "运行一些协议后,它们将显示在此处。", "num_units": "{{num}}毫米", "offline_deck_configuration": "工作站必须连接网络才能查看甲板配置", "offline_instruments_and_modules": "工作站必须连接网络才能查看已连接的设备和模块", @@ -131,12 +132,12 @@ "protocol_analysis_failed": "协议APP分析失败。", "protocol_analysis_stale": "协议分析已过期。", "protocol_details_page_reanalyze": "前往协议详情页面重新分析。", - "ready_to_run": "运行工作准备完成", "ready": "准备就绪", + "ready_to_run": "运行工作准备完成", "recalibrate_gripper": "重新校准转板抓手", "recalibrate_now": "立即重新校准", - "recalibrate_pipette_offset": "重新校准移液器偏移", "recalibrate_pipette": "重新校准移液器", + "recalibrate_pipette_offset": "重新校准移液器偏移", "recent_protocol_runs": "最近的协议运行", "rerun_loading": "数据完全加载前,禁止协议重新运行", "rerun_now": "立即重新运行协议", @@ -146,17 +147,17 @@ "right": "右侧", "robot_control_not_available": "运行过程中某些工作站控制功能不可用", "robot_initializing": "初始化中...", + "run": "运行", "run_a_protocol": "运行协议", "run_again": "再次运行", "run_duration": "运行时长", - "run": "运行", "select_options": "选择选项", "serial_number": "序列号", "set_block_temp": "设置温度", "set_block_temperature": "设置模块温度", + "set_engage_height": "设置启用高度", "set_engage_height_and_enter_integer": "为此磁力模块设置启用高度。请输入一个介于{{lower}}和{{higher}}之间的整数。", "set_engage_height_for_module": "为{{name}}设置启用高度", - "set_engage_height": "设置启用高度", "set_lid_temperature": "设置上盖温度", "set_shake_of_hs": "为此模块设置转速。", "set_shake_speed": "设置震荡速度", @@ -173,8 +174,8 @@ "target_temp": "目标温度:{{temp}}°C", "tc_block": "模块", "tc_lid": "上盖", - "tc_set_temperature_body": "预热或预冷您的热循环模块的{{part}}。请输入介于{{min}}°C 和{{max}}°C之间的一个整数。", "tc_set_temperature": "为{{name}}设置温度{{part}}", + "tc_set_temperature_body": "预热或预冷您的热循环模块的{{part}}。请输入介于{{min}}°C 和{{max}}°C之间的一个整数。", "tempdeck_slideout_body": "预热或冷却您的{{model}}。输入4°C至96°C之间的一个整数。", "tempdeck_slideout_title": "为{{name}}设置温度", "temperature": "温度", @@ -184,12 +185,12 @@ "trash": "垃圾桶", "update_now": "立即更新", "updating_firmware": "正在更新固件...", - "usb_port_not_connected": "USB未连接", "usb_port": "USB端口-{{port}}", + "usb_port_not_connected": "USB未连接", "version": "版本{{version}}", + "view": "查看", "view_pipette_setting": "移液器设置", "view_run_record": "查看协议运行记录", - "view": "查看", "waste_chute": "外置垃圾槽", "welcome_modal_description": "运行协议、管理设备及查看工作站状态的地方。", "welcome_to_your_dashboard": "欢迎来到您的控制面板!", diff --git a/app/src/assets/localization/zh/device_settings.json b/app/src/assets/localization/zh/device_settings.json index ecd81c941dd..40e59b5c354 100644 --- a/app/src/assets/localization/zh/device_settings.json +++ b/app/src/assets/localization/zh/device_settings.json @@ -3,6 +3,7 @@ "about_calibration_description": "为了让工作站精确移动,您需要对其进行校准。位置校准分为三部分:甲板校准、移液器偏移校准和吸头长度校准。", "about_calibration_description_ot3": "为了让工作站精确移动,您需要对其进行校准。移液器和转板抓手校准是一个自动化过程,使用校准探头或销钉。校准完成后,您可以将校准数据以JSON文件的形式保存到计算机中。", "about_calibration_title": "关于校准", + "add_new": "添加新的...", "advanced": "高级", "alpha_description": "警告:alpha版本功能完整,但可能包含重大错误。", "alternative_security_types": "可选的安全类型", @@ -10,10 +11,12 @@ "apply_historic_offsets": "应用耗材偏移校准数据", "are_you_sure_you_want_to_disconnect": "您确定要断开与{{ssid}}的连接吗?", "attach_a_pipette_before_calibrating": "在执行校准之前,请安装移液器", + "authentication": "验证", "boot_scripts": "启动脚本", "both": "两者", "browse_file_system": "浏览文件系统", "bug_fixes": "错误修复", + "but_we_expected": "但我们预计", "calibrate_deck": "校准甲板", "calibrate_deck_description": "适用于没有在甲板上蚀刻十字的2019年之前的工作站。", "calibrate_deck_to_dots": "根据校准点校准甲板", @@ -24,11 +27,14 @@ "calibration": "校准", "calibration_health_check_description": "检查关键校准点的精度,无需重新校准工作站。", "calibration_health_check_title": "校准运行状况检查", + "cancel_software_update": "取消软件更新", "change_network": "更改网络", "characters_max": "最多17个字符", "check_for_updates": "检查更新", + "check_to_verify_update": "检查设备的设置页面以验证更新是否成功", "checking_for_updates": "正在检查更新", "choose": "选择...", + "choose_a_network": "选择网络...", "choose_file": "选择文件", "choose_network_type": "选择网络类型", "choose_reset_settings": "选择重置设置", @@ -50,13 +56,14 @@ "clear_option_runs_history": "清除协议运行历史", "clear_option_runs_history_subtext": "清除所有协议的过往运行信息。点击并应用", "clear_option_tip_length_calibrations": "清除吸头长度校准", - "cancel_software_update": "取消软件更新", "complete_and_restart_robot": "完成并重新启动工作站", "confirm_device_reset_description": "这将永久删除所有协议、校准和其他数据。您需要重新进行初始设置才能再次使用工作站。", "confirm_device_reset_heading": "您确定要重置您的设备吗?", "connect": "连接", "connect_the_estop_to_continue": "连接紧急停止按钮以继续", + "connect_to_ssid": "连接到 {{ssid}}", "connect_to_wifi_network": "连接到Wi-Fi网络", + "connect_to_wifi_network_failure": "您的设备无法连接到 Wi-Fi 网络 {{ssid}}", "connect_via": "通过{{type}}连接", "connect_via_usb_description_1": "1. 将 USB A-to-B 连接线连接到工作站的 USB-B 端口。", "connect_via_usb_description_2": "2. 将电缆连接到计算机上的一个空闲USB端口。", @@ -65,6 +72,7 @@ "connected_to_ssid": "已连接到{{ssid}}", "connected_via": "通过{{networkInterface}}连接", "connecting_to": "正在连接到{{ssid}}...", + "connecting_to_wifi_network": "连接到 Wi-Fi 网络 {{ssid}}", "connection_description_ethernet": "连接到您实验室的有线网络。", "connection_description_wifi": "在您的实验室中找到一个网络,或者输入您自己的网络。", "connection_to_robot_lost": "与工作站的连接中断", @@ -81,7 +89,6 @@ "device_reset_description": "将耗材校准、启动脚本和/或工作站校准重置为出厂设置。", "device_reset_slideout_description": "选择单独的设置以仅清除特定的数据类型。", "device_resets_cannot_be_undone": "重置无法撤销", - "release_notes": "发行说明", "directly_connected_to_this_computer": "直接连接到这台计算机。", "disconnect": "断开连接", "disconnect_from_ssid": "断开与{{ssid}}的连接", @@ -97,6 +104,7 @@ "display_sleep_settings": "屏幕睡眠设置", "do_not_turn_off": "这可能需要最多{{minutes}}分钟。请不要关闭工作站。", "done": "完成", + "downgrade": "降级", "download": "下载", "download_calibration_data": "下载校准日志", "download_error": "下载错误日志", @@ -110,6 +118,7 @@ "enable_status_light_description": "打开或关闭工作站前部的指示LED灯条。", "engaged": "已连接", "enter_factory_password": "输入工厂密码", + "enter_name_security_type": "输入网络名称和安全类型。", "enter_network_name": "输入网络名称", "enter_password": "输入密码", "estop": "紧急停止按钮", @@ -128,6 +137,8 @@ "factory_resets_cannot_be_undone": "工厂重置无法撤销。", "failed_to_connect_to_ssid": "无法连接到{{ssid}}", "feature_flags": "功能标志", + "field_is_required": "需要{{field}} ", + "find_and_join_network": "查找并加入 Wi-Fi 网络", "finish_setup": "完成设置", "firmware_version": "固件版本", "fully_calibrate_before_checking_health": "在检查校准健康之前,请完全校准您的工作站", @@ -155,6 +166,7 @@ "last_calibrated_label": "最后校准", "launch_jupyter_notebook": "启动Jupyter Notebook", "legacy_settings": "遗留设置", + "likely_incorrect_password": "可能网络密码不正确。", "mac_address": "MAC地址", "manage_oem_settings": "管理OEM设置", "minutes": "{{minute}}分钟", @@ -172,17 +184,22 @@ "name_your_robot": "给您的工作站起个名字", "name_your_robot_description": "别担心,您可以在设置中随时更改这个名称。", "need_another_security_type": "需要另一种安全类型吗?", + "network_is_unsecured": "Wi-Fi 网络 {{ssid}} 不安全", "network_name": "网络名称", + "network_requires_auth": "Wi-Fi 网络 {{ssid}} 需要 802.1X 身份验证", + "network_requires_wpa_password": "Wi-Fi 网络 {{ssid}} 需要 WPA2 密码", "network_settings": "网络设置", "networking": "网络连接", "never": "从不", "new_features": "新功能", "next_step": "下一步", + "no_calibration_required": "无需校准", "no_connection_found": "未找到连接", "no_gripper_attached": "未连接转板抓手", "no_modules_attached": "未连接模块", "no_network_found": "未找到网络", "no_pipette_attached": "未连接移液器", + "no_update_files": "无法检索此设备的更新状态。请确保您的计算机已连接到互联网,然后稍后重试。", "none_description": "不推荐", "not_calibrated": "尚未校准", "not_calibrated_short": "未校准", @@ -194,11 +211,13 @@ "not_now": "不是现在", "oem_mode": "OEM模式", "off": "关闭", - "one_hour": "1小时", "on": "开启", + "one_hour": "1小时", "other_networks": "其他网络", + "other_robot_updating": "无法更新,因为该APP目前正在更新其他设备。", "password": "密码", "password_error_message": "至少需要8个字符", + "password_not_long_enough": "密码必须至少为 {{minLength}} 字符", "pause_protocol": "当工作站前门打开时暂停协议", "pause_protocol_description": "启用后,在运行过程中打开工作站前门,工作站会在完成当前动作后暂停。", "pipette_calibrations_description": "使用校准探头来确定移液器相对于甲板槽上的精密切割方格的确切位置。", @@ -208,6 +227,7 @@ "pipette_offset_calibration_recommended": "建议进行移液器偏移校准", "pipette_offset_calibrations_history": "查看所有移液器偏移校准历史", "pipette_offset_calibrations_title": "移液器偏移校准", + "please_check_credentials": "请仔细检查你的网络凭证", "privacy": "隐私", "problem_during_update": "此次更新耗时比平常要长。", "proceed_without_updating": "跳过更新以继续", @@ -220,6 +240,7 @@ "recalibrate_tip_and_pipette": "重新校准吸头长度和移液器偏移量", "recalibration_recommended": "建议重新校准", "reinstall": "重新安装", + "release_notes": "发行说明", "remind_me_later": "稍后提醒我", "rename_robot": "重命名工作站", "rename_robot_input_error": "哎呀!工作站名称必须遵循字符计数和限制。", @@ -237,9 +258,12 @@ "returns_your_device_to_new_state": "这将使您的设备恢复到新的状态。", "robot_busy_protocol": "当协议正在运行时,此工作站无法更新", "robot_calibration_data": "工作站校准数据", + "robot_has_bad_capabilities": "设备配置不正确", "robot_initializing": "正在初始化工作站...", "robot_name": "工作站名称", "robot_operating_update_available": "工作站操作系统更新可用", + "robot_reconnected_with version": "设备重新获取版本", + "robot_requires_premigration": "系统必须先更新此设备,然后才能进行自定义更新", "robot_serial_number": "工作站序列号", "robot_server_version": "工作站服务器版本", "robot_settings": "工作站设置", @@ -258,7 +282,9 @@ "select_a_network": "选择一个网络", "select_a_security_type": "选择一个安全类型", "select_all_settings": "选择所有设置", + "select_auth_method_short": "选择身份验证方法", "select_authentication_method": "为您所选的网络选择身份验证方法。", + "select_file": "选择文件", "sending_software": "正在发送软件...", "serial": "序列号", "setup_mode": "设置模式", @@ -274,6 +300,9 @@ "subnet_mask": "子网掩码", "successfully_connected": "成功连接!", "successfully_connected_to_network": "已成功连接到{{ssid}}!", + "successfully_connected_to_ssid": "您的设备已成功连接至 Wi-Fi 网络 {{ssid}}", + "successfully_connected_to_wifi": "成功连接 Wi-Fi", + "successfully_disconnected_from_wifi": "已成功断开 Wi-Fi 连接", "supported_protocol_api_versions": "支持的协议API版本", "text_size": "文本大小", "text_size_description": "所有屏幕上的文本都会根据您在下方选择的大小进行调整。", @@ -285,18 +314,29 @@ "troubleshooting": "故障排查", "try_again": "再试一次", "try_restarting_the_update": "尝试重新启动更新。", + "unable_to_cancel_update": "无法取消正在进行的更新", + "unable_to_commit_update": "无法提交更新", + "unable_to_connect": "无法连接到 Wi-Fi", + "unable_to_disconnect": "无法断开 Wi-Fi 连接", + "unable_to_find_robot_with_name": "无法找到在线设备", + "unable_to_find_system_file": "无法找到要更新的系统文件", + "unable_to_restart": "无法重启设备", + "unable_to_start_update_session": "无法启动更新", "up_to_date": "最新的", "update_available": "有可用更新", "update_channel_description": "稳定版接收最新的稳定版发布。Beta 版允许您在新功能在稳定版发布前先行试用,但这些新功能尚未完成测试。", "update_complete": "更新完成!", "update_found": "发现更新!", + "update_requires_restarting_robot": "更新工作站软件需要重启工作站", "update_robot_now": "现在更新工作站", "update_robot_software": "使用本地文件(.zip)手动更新工作站软件", + "update_server_unavailable": "无法更新,因为您设备的更新服务器没有响应。", + "update_unavailable": "无法更新", "updating": "正在更新", - "update_requires_restarting_robot": "更新工作站软件需要重启工作站", + "upgrade": "升级", + "upload_custom_logo": "上传自定义Logo", "upload_custom_logo_description": "上传一个Logo,用于工作站启动时显示。", "upload_custom_logo_dimensions": "Logo必须符合 1024 x 600 的尺寸,且是 PNG 文件(.png)。", - "upload_custom_logo": "上传自定义Logo", "usage_settings": "使用设置", "usb": "USB", "usb_to_ethernet_description": "正在查找 USB-to-Ethernet 适配器信息?", diff --git a/app/src/assets/localization/zh/devices_landing.json b/app/src/assets/localization/zh/devices_landing.json index 8e6af9d5ba9..4c649c41b02 100644 --- a/app/src/assets/localization/zh/devices_landing.json +++ b/app/src/assets/localization/zh/devices_landing.json @@ -23,9 +23,9 @@ "lights_on": "开启灯光", "loading": "加载中", "looking_for_robots": "寻找工作站", - "ninety_six_mount": "左侧+右侧安装支架", "make_sure_robot_is_connected": "确保工作站已连接到此计算机", "modules": "模块", + "ninety_six_mount": "左侧+右侧安装支架", "no_robots_found": "未找到工作站", "not_available": "不可用({{count}})", "ot2_quickstart_guide": "OT-2 快速入门指南", diff --git a/app/src/assets/localization/zh/drop_tip_wizard.json b/app/src/assets/localization/zh/drop_tip_wizard.json index a5ae8faebfc..307c2aa7e72 100644 --- a/app/src/assets/localization/zh/drop_tip_wizard.json +++ b/app/src/assets/localization/zh/drop_tip_wizard.json @@ -16,9 +16,9 @@ "drop_tip_failed": "丢弃吸头操作未能完成,请联系技术支持获取帮助。", "drop_tips": "丢弃吸头", "error_dropping_tips": "丢弃吸头时发生错误", - "exit_and_home_pipette": "退出并归位移液器", - "exit_screen_title": "在完成吸头丢弃前退出?", "exit": "退出", + "exit_and_home_pipette": "退出并归位移液器", + "fixed_trash_in_12": "固定垃圾存放位置为12", "getting_ready": "正在准备…", "go_back": "返回", "jog_too_far": "移动过远?", @@ -30,7 +30,6 @@ "position_and_drop_tip": "确保移液器吸头尖端位于指定位置的正上方并保持水平。如果不是,请使用下面的控制键或键盘微调移液器直到正确位置。", "position_the_pipette": "调整移液器位置", "remove_any_attached_tips": "移除任何已安装的吸头", - "remove_the_tips": "在协议中再次使用前,您可能需要从{{mount}}移液器上移除吸头。", "remove_the_tips_from_pipette": "在协议中再次使用前,您可能需要从移液器上移除吸头。", "remove_the_tips_manually": "手动移除吸头,然后使龙门架回原点。在拾取吸头的状态下归位可能导致移液器吸入液体并损坏。", "remove_tips": "移除吸头", @@ -38,8 +37,8 @@ "select_blowout_slot_odd": "您可以将液体吹入耗材中。
龙门架移动到选定的板位后,使用位置控制按键将移液器移动到吹出液体的确切位置。", "select_drop_tip_slot": "您可以将吸头返回吸头架或丢弃它们。在右侧的甲板图上选择您想丢弃吸头的板位。确认后龙门架将移动到选定的板位。", "select_drop_tip_slot_odd": "您可以将吸头放回吸头架或丢弃它们。
龙门架移动到选定的板位后,使用位置控制按键将移液器移动到丢弃吸头的确切位置。", - "skip_and_home_pipette": "跳过并归位移液器", "skip": "跳过", + "skip_and_home_pipette": "跳过并归位移液器", "stand_back_blowing_out": "请远离,工作站正在吹出液体", "stand_back_dropping_tips": "请远离,工作站正在丢弃吸头", "stand_back_robot_in_motion": "请远离,工作站正在移动", diff --git a/app/src/assets/localization/zh/error_recovery.json b/app/src/assets/localization/zh/error_recovery.json index dddf7923d4b..a740eac779d 100644 --- a/app/src/assets/localization/zh/error_recovery.json +++ b/app/src/assets/localization/zh/error_recovery.json @@ -6,9 +6,9 @@ "before_you_begin": "开始前", "begin_removal": "开始移除", "blowout_failed": "吹出液体失败", - "overpressure_is_usually_caused": "探测器感应到压力过大通常是由吸头碰撞到实验用品、吸头堵塞或吸取/排出粘稠液体速度过快引起。如果问题持续存在,请取消运行并对协议进行必要的修改。", "cancel_run": "取消运行", "canceling_run": "正在取消运行", + "carefully_move_labware": "小心地移开放错位置的实验用品并清理溢出的液体。继续操作之前请关闭设备前门。", "change_location": "更改位置", "change_tip_pickup_location": "更换拾取吸头的位置", "choose_a_recovery_action": "选择恢复操作", @@ -19,10 +19,12 @@ "continue": "继续", "continue_run_now": "现在继续运行", "continue_to_drop_tip": "继续丢弃吸头", + "do_you_need_to_blowout": "首先,请问需要排出枪头内的液体吗?", + "door_open_robot_home": "在手动移动实验用品前,设备需要安全归位。", "ensure_lw_is_accurately_placed": "确保实验耗材已准确放置在甲板槽中,防止进一步出现错误", + "error": "错误", "error_details": "错误详情", "error_on_robot": "{{robot}}上的错误", - "error": "错误", "failed_dispense_step_not_completed": "中断运行的最后一步液体排出失败,恢复程序将不会继续运行这一步骤,请手动完成这一步的移液操作。运行将继续从下一步开始。继续之前,请关闭工作站门。", "failed_step": "失败步骤", "first_is_gripper_holding_labware": "首先,抓扳手是否夹着实验耗材?", @@ -31,6 +33,9 @@ "gripper_errors_occur_when": "当抓扳手停滞或与甲板上另一物体碰撞时,会发生抓扳手错误,这通常是由于实验耗材放置不当或实验耗材偏移不准确所致", "gripper_releasing_labware": "抓扳手正在释放实验耗材", "gripper_will_release_in_s": "抓扳手将在{{seconds}}秒后释放实验耗材", + "home_and_retry": "归位并重试该步骤", + "home_gantry": "归位", + "home_now": "现在归位", "homing_pipette_dangerous": "如果移液器中有液体,将{{mount}}移液器归位可能会损坏它。您必须在使用移液器之前取下所有吸头。", "if_issue_persists_gripper_error": "如果问题持续存在,请取消运行并重新运行抓扳手校准", "if_issue_persists_overpressure": "如果问题持续存在,请取消运行并对协议进行必要的更改", @@ -40,6 +45,7 @@ "ignore_error_and_skip": "忽略错误并跳到下一步", "ignore_only_this_error": "仅忽略此错误", "ignore_similar_errors_later_in_run": "要在后续的运行中忽略类似错误吗?", + "inspect_the_robot": "首先,检查设备以确保它已准备好从下一步继续运行。然后,关闭设备前门,再继续操作。", "labware_released_from_current_height": "将从当前高度释放实验耗材", "launch_recovery_mode": "启动恢复模式", "manually_fill_liquid_in_well": "手动填充孔位{{well}}中的液体", @@ -48,29 +54,36 @@ "manually_move_lw_on_deck": "手动移动实验耗材", "manually_replace_lw_and_retry": "手动更换实验耗材并重试此步骤", "manually_replace_lw_on_deck": "手动更换实验耗材", + "na": "N/A", "next_step": "下一步", "next_try_another_action": "接下来,您可以尝试另一个恢复操作或取消运行。", "no_liquid_detected": "未检测到液体", + "overpressure_is_usually_caused": "探测器感应到压力过大通常是由吸头碰撞到实验用品、吸头堵塞或吸取/排出粘稠液体速度过快引起。如果问题持续存在,请取消运行并对协议进行必要的修改。", "pick_up_tips": "取吸头", "pipette_overpressure": "移液器超压", - "preserve_aspirated_liquid": "首先,您需要保留已吸取的液体吗?", + "prepare_deck_for_homing": "整理甲板,准备归位", "proceed_to_cancel": "继续取消", + "proceed_to_home": "归位中", "proceed_to_tip_selection": "继续选择吸头", "recovery_action_failed": "{{action}}失败", "recovery_mode": "恢复模式", "recovery_mode_explanation": "恢复模式为您提供运行错误后的手动处理引导。
您可以进行调整以确保发生错误时正在进行的步骤可以完成,或者选择取消协议。当做出调整且未检测到后续错误时,该模式操作完成。根据导致错误的条件,系统将提供相应的调整选项。", - "release_labware_from_gripper": "从抓板手中释放实验耗材", "release": "释放", + "release_labware_from_gripper": "从抓板手中释放实验耗材", "remove_any_attached_tips": "移除任何已安装的吸头", + "replace_tips_and_select_loc_partial_tip": "更换吸头并选择最后用于偏转移液吸头拾取的位置。", "replace_tips_and_select_location": "建议更换吸头并选择最后一次取吸头的位置。", "replace_used_tips_in_rack_location": "在吸头板位{{location}}更换已使用的吸头", "replace_with_new_tip_rack": "更换新的吸头盒", "resume": "继续", - "retrying_step_succeeded": "重试步骤{{step}}成功", + "retry_dropping_tip": "重试弹出吸头", "retry_now": "现在重试", + "retry_picking_up_tip": "重试拾取吸头", "retry_step": "重试步骤", "retry_with_new_tips": "使用新吸头重试", "retry_with_same_tips": "使用相同吸头重试", + "retrying_step_succeeded": "重试步骤{{step}}成功", + "retrying_step_succeeded_na": "重试当前步骤成功。", "return_to_menu": "返回菜单", "robot_door_is_open": "工作站前门已打开", "robot_is_canceling_run": "工作站正在取消运行", @@ -83,25 +96,30 @@ "robot_will_retry_with_tips": "工作站将使用新吸头重试失败的步骤。", "run_paused": "运行暂停", "select_tip_pickup_location": "选择取吸头位置", - "skipping_to_step_succeeded": "跳转到步骤{{step}}成功", "skip_and_home_pipette": "跳过并归位移液器", "skip_to_next_step": "跳到下一步", "skip_to_next_step_new_tips": "使用新吸头跳到下一步", "skip_to_next_step_same_tips": "使用相同吸头跳到下一步", + "skipping_to_step_succeeded": "跳转到步骤{{step}}成功", + "skipping_to_step_succeeded_na": "跳至下一步成功。", + "stall_or_collision_detected_when": "当设备电机堵塞时,检测到失速或碰撞", + "stall_or_collision_error": "失速或碰撞", "stand_back": "请远离,工作站正在运行", "stand_back_picking_up_tips": "请远离,正在拾取吸头", "stand_back_resuming": "请远离,正在恢复当前步骤", "stand_back_retrying": "请远离,正在重试失败步骤", "stand_back_skipping_to_next_step": "请远离,正在跳到下一步骤", "take_any_necessary_precautions": "在接住实验耗材之前,请采取必要的预防措施。确认后,夹爪将开始倒计时再释放。", - "take_necessary_actions_failed_pickup": "首先,采取任何必要的行动,让工作站重新尝试移液器拾取。然后,在继续之前关闭工作站门。", "take_necessary_actions": "首先,采取任何必要的行动,让工作站重新尝试失败的步骤。然后,在继续之前关闭工作站门。", + "take_necessary_actions_failed_pickup": "首先,采取任何必要的行动,让工作站重新尝试移液器拾取。然后,在继续之前关闭工作站门。", + "take_necessary_actions_failed_tip_drop": "首先,采取一切必要的措施,让设备准备好重试弹出吸头。然后,关闭设备前门,再继续操作。", + "take_necessary_actions_home": "采取一切必要的措施,准备让设备归位。继续操作之前请关闭设备前门。", "terminate_remote_activity": "终止远程活动", + "the_robot_must_return_to_home_position": "设备必须归位才能继续", "tip_drop_failed": "丢弃吸头失败", "tip_not_detected": "未检测到吸头", "tip_presence_errors_are_caused": "吸头识别错误通常是由实验器皿放置不当或器皿偏移不准确引起的。", "view_error_details": "查看错误详情", "view_recovery_options": "查看恢复选项", - "you_can_still_drop_tips": "在继续选择吸头之前,您仍然可以丢弃移液器上现存的吸头。", - "you_may_want_to_remove": "在协议中再次使用之前,您可能需要从{{mount}}移液器上移除吸头。" + "you_can_still_drop_tips": "在继续选择吸头之前,您仍然可以丢弃移液器上现存的吸头。" } diff --git a/app/src/assets/localization/zh/gripper_wizard_flows.json b/app/src/assets/localization/zh/gripper_wizard_flows.json index 6617e15d83a..00319f11f6d 100644 --- a/app/src/assets/localization/zh/gripper_wizard_flows.json +++ b/app/src/assets/localization/zh/gripper_wizard_flows.json @@ -5,19 +5,17 @@ "before_you_begin": "开始之前", "begin_calibration": "开始校准", "calibrate_gripper": "校准转板抓手", - "calibration_pin": "校准钉", "calibration_pin_touching": "校准钉将触碰甲板{{slot}}中的校准块,以确定其精确位置。", "complete_calibration": "完成校准", "continue": "继续", "continue_calibration": "继续校准", "detach_gripper": "卸下转板抓手", - "firmware_updating": "需要固件更新,设备正在更新中...", "firmware_up_to_date": "固件已为最新版本。", + "firmware_updating": "需要固件更新,设备正在更新中...", "get_started": "开始操作", "gripper_calibration": "转板抓手校准", "gripper_recalibration": "转板抓手重新校准", "gripper_successfully_attached": "转板抓手已成功安装", - "hex_screwdriver": "2.5mm 六角螺丝刀", "hold_gripper_and_loosen_screws": "用手扶住转板抓手,首先松开上方螺丝,再松开下方螺丝。(螺丝固定于抓手上,不会脱落。)之后小心卸下抓手。", "insert_pin_into_front_jaw": "将校准钉插入前夹爪", "insert_pin_into_rear_jaw": "将校准钉插入后夹爪", diff --git a/app/src/assets/localization/zh/heater_shaker.json b/app/src/assets/localization/zh/heater_shaker.json index 249f1cc6138..efc48439868 100644 --- a/app/src/assets/localization/zh/heater_shaker.json +++ b/app/src/assets/localization/zh/heater_shaker.json @@ -4,43 +4,43 @@ "cannot_shake": "模块闩锁打开时无法执行震荡混匀命令", "close_labware_latch": "关闭耗材闩锁", "close_latch": "关闭闩锁", - "closed_and_locked": "关闭并锁定", "closed": "已关闭", + "closed_and_locked": "关闭并锁定", "closing": "正在关闭", "complete": "完成", "confirm_attachment": "确认已连接", "confirm_heater_shaker_modal_attachment": "确认热震荡模块已连接", "continue_shaking_protocol_start_prompt": "协议启动时是否继续执行震荡混匀命令?", + "deactivate": "停用", "deactivate_heater": "停止加热", "deactivate_shaker": "停止震荡混匀", - "deactivate": "停用", "heater_shaker_in_slot": "在继续前,请在板位{{slotName}}中安装{{moduleName}}", "heater_shaker_is_shaking": "热震荡模块当前正在震荡混匀", "keep_shaking_start_run": "继续震荡混匀并开始运行", - "labware_latch": "耗材闩锁", "labware": "耗材", + "labware_latch": "耗材闩锁", "min_max_rpm": "{{min}}-{{max}}rpm", "module_anchors_extended": "运行开始前,应将模块下方的固定位的漏丝拧紧,确保模块稳固跟甲板结合", "module_in_slot": "{{moduleName}}位于板位{{slotName}}槽中", "module_should_have_anchors": "模块应将两个固定锚完全伸出,以确保稳固地连接到甲板上", + "open": "打开", "open_labware_latch": "打开耗材闩锁", "open_latch": "打开闩锁", - "open": "打开", "opening": "正在打开", "proceed_to_run": "继续运行", "set_shake_speed": "设置震荡混匀速度", "set_temperature": "设置模块温度", "shake_speed": "震荡混匀速度", "show_attachment_instructions": "显示固定操作安装说明", - "stop_shaking_start_run": "停止震荡混匀并开始运行", "stop_shaking": "停止震荡混匀", + "stop_shaking_start_run": "停止震荡混匀并开始运行", "t10_torx_screwdriver": "{{name}}型螺丝刀", "t10_torx_screwdriver_subtitle": "热震荡模块附带。使用其他尺寸可能会损坏模块螺丝", + "test_shake": "测试震荡混匀", "test_shake_banner_information": "测试震荡混匀功能前,如果想往热震荡模块转移耗材,需要在控制页面控制模块开启闩锁", "test_shake_banner_labware_information": "测试震荡混匀功能前,如果想往热震荡模块转移{{labware}},需要控制模块闩锁", "test_shake_slideout_banner_info": "测试震荡混匀功能前,如果想往热震荡模块转移耗材,需要在控制页面控制模块开启闩锁", "test_shake_troubleshooting_slideout_description": "请重新查看模块固定安装及其适配器安装相关说明", - "test_shake": "测试震荡混匀", "thermal_adapter_attached_to_module": "适配器应已连接到模块上", "troubleshoot_step_1": "返回步骤1查看模块固定安装相关说明", "troubleshoot_step_3": "返回步骤3查看模块适配器安装相关说明", diff --git a/app/src/assets/localization/zh/incompatible_modules.json b/app/src/assets/localization/zh/incompatible_modules.json index 7e6da2f253e..0ff716c1326 100644 --- a/app/src/assets/localization/zh/incompatible_modules.json +++ b/app/src/assets/localization/zh/incompatible_modules.json @@ -1,7 +1,7 @@ { "incompatible_modules_attached": "检测到不适用模块,", - "remove_before_running_protocol": "运行协议前请移除以下硬件:", + "is_not_compatible": "{{module_name}}不适用于{{robot_type}},", "needs_your_assistance": "{{robot_name}}需要您的协助", - "remove_before_using": "使用此工作站前,请移除不适用模块.", - "is_not_compatible": "{{module_name}}不适用于{{robot_type}}," + "remove_before_running_protocol": "运行协议前请移除以下硬件:", + "remove_before_using": "使用此工作站前,请移除不适用模块." } diff --git a/app/src/assets/localization/zh/labware_details.json b/app/src/assets/localization/zh/labware_details.json index ba1183c2ea4..76ade48d727 100644 --- a/app/src/assets/localization/zh/labware_details.json +++ b/app/src/assets/localization/zh/labware_details.json @@ -8,8 +8,8 @@ "generic": "通用型", "height": "高度", "length": "长度", - "manufacturer_number": "制造商/目录编号", "manufacturer": "制造商", + "manufacturer_number": "制造商/目录编号", "max_volume": "最大容量", "measurements": "尺寸 (mm)", "na": "不适用", @@ -21,8 +21,8 @@ "u": "U型底", "v": "V型底", "various": "多种", - "well_count": "孔数", "well": "孔", + "well_count": "孔数", "width": "宽度", "x_offset": "X-初始位置", "x_size": "X-尺寸", diff --git a/app/src/assets/localization/zh/labware_landing.json b/app/src/assets/localization/zh/labware_landing.json index 386114541f3..f209e48c3e5 100644 --- a/app/src/assets/localization/zh/labware_landing.json +++ b/app/src/assets/localization/zh/labware_landing.json @@ -3,20 +3,20 @@ "cancel": "取消", "cannot-run-python-missing-labware": "工作站缺少耗材定义,无法运行Python协议。", "category": "类别", - "choose_file_to_upload": "或从您的计算机中选择文件上传。", "choose_file": "选择文件", + "choose_file_to_upload": "或从您的计算机中选择文件上传。", "copied": "已复制!", "create_new_def": "创建新的自定义耗材", "custom_def": "自定义耗材", "date_added": "添加日期", "def_moved_to_trash": "该耗材将被转移到这台电脑的回收站,可能无法恢复。", - "delete_this_labware": "删除此耗材?", "delete": "删除", + "delete_this_labware": "删除此耗材?", "duplicate_labware_def": "复制耗材", "error_importing_file": "{{filename}}导入错误。", "go_to_def": "前往耗材页面", - "import_custom_def": "导入自定义耗材", "import": "导入", + "import_custom_def": "导入自定义耗材", "imported": "{{filename}}已导入。", "invalid_labware_def": "无效耗材", "labware": "耗材", diff --git a/app/src/assets/localization/zh/labware_position_check.json b/app/src/assets/localization/zh/labware_position_check.json index cb27f78e66c..57fd1552a65 100644 --- a/app/src/assets/localization/zh/labware_position_check.json +++ b/app/src/assets/localization/zh/labware_position_check.json @@ -25,8 +25,8 @@ "confirm_position_and_pick_up_tip": "确认位置,取吸头", "confirm_position_and_return_tip": "确认位置,将吸头返回至板位{{next_slot}}并复位", "detach_probe": "移除校准探头", - "ensure_nozzle_position_odd": "请检查并确认{{tip_type}}位于{{item_location}}正上方并水平对齐。如果位置不正确,请点击移动移液器,然后微调移液器直至完全对齐。", "ensure_nozzle_position_desktop": "请检查并确认{{tip_type}}位于{{item_location}}正上方并水平对齐。如果位置不正确,请使用下方的控制按键或键盘微调移液器直至完全对齐。", + "ensure_nozzle_position_odd": "请检查并确认{{tip_type}}位于{{item_location}}正上方并水平对齐。如果位置不正确,请点击移动移液器,然后微调移液器直至完全对齐。", "exit_screen_confirm_exit": "不保存耗材校准数据并退出", "exit_screen_go_back": "返回耗材位置校准", "exit_screen_subtitle": "如果您现在退出,所有耗材校准数据都将不保留,且无法恢复。", @@ -35,9 +35,10 @@ "install_probe": "从存储位置取出校准探头,将探头的锁套旋钮按顺时针方向拧松。对准图示位置,将校准探头向上轻推并压到顶部,使探头在{{location}}移液器吸嘴上压紧。随后将锁套旋钮按逆时针方向拧紧,并轻拉确认是否固定稳妥。", "jog_controls_adjustment": "需要进行调整吗?", "jupyter_notebook": "Jupyter Notebook", + "labware": "耗材", "labware_display_location_text": "甲板板位{{slot}}", - "labware_offset_data": "耗材校准数据", "labware_offset": "耗材校准数据", + "labware_offset_data": "耗材校准数据", "labware_offsets_deleted_warning": "一旦开始耗材位置校准,之前创建的耗材校准数据将会丢失。", "labware_offsets_summary_labware": "耗材", "labware_offsets_summary_location": "位置", @@ -46,22 +47,21 @@ "labware_position_check_description": "耗材位置校准是一个引导式工作流程,为了提高实验中移液器的位置精确度,它会检查甲板上的每一个耗材位置。首先检查吸头盒,然后检查协议中使用到的其它所有耗材。", "labware_position_check_overview": "耗材位置校准概览", "labware_position_check_title": "耗材位置校准", - "labware_step_detail_labware_plural": "吸头应位于 {{labware_name}} 第一列正上方,居中对齐,并且与耗材顶部水平对齐。", "labware_step_detail_labware": "吸头应位于 {{labware_name}} 的A1孔正上方,居中对齐,并且与耗材顶部水平对齐。", + "labware_step_detail_labware_plural": "吸头应位于 {{labware_name}} 第一列正上方,居中对齐,并且与耗材顶部水平对齐。", "labware_step_detail_link": "查看如何判断移液器是否居中", "labware_step_detail_modal_heading": "如何判断移液器是否居中且水平对齐", + "labware_step_detail_modal_nozzle": "为确保移液器吸嘴完全居中,请额外从OT-2的另一侧进行检查。", "labware_step_detail_modal_nozzle_image_1_text": "从正前方看,似乎已经居中...", "labware_step_detail_modal_nozzle_image_2_nozzle_text": "移液器吸嘴未居中", "labware_step_detail_modal_nozzle_image_2_text": "...但从侧面看,需要调整", + "labware_step_detail_modal_nozzle_or_tip": "为确保吸嘴或吸头与耗材顶部水平对齐,请水平直视进行判断,或在吸嘴与吸头间插入一张纸片辅助判断。", "labware_step_detail_modal_nozzle_or_tip_image_1_text": "从俯视角度看,似乎是水平的...", "labware_step_detail_modal_nozzle_or_tip_image_2_nozzle_text": "移液器吸嘴不水平", "labware_step_detail_modal_nozzle_or_tip_image_2_text": "...但从水平高度看,需要调整", "labware_step_detail_modal_nozzle_or_tip_image_3_text": "如遇觉得难以判断,请在吸嘴与吸头之间放入一张常规纸张。当这张纸能刚好卡在两者之间时,可确认高度位置。", - "labware_step_detail_modal_nozzle_or_tip": "为确保吸嘴或吸头与耗材顶部水平对齐,请水平直视进行判断,或在吸嘴与吸头间插入一张纸片辅助判断。", - "labware_step_detail_modal_nozzle": "为确保移液器吸嘴完全居中,请额外从OT-2的另一侧进行检查。", - "labware_step_detail_tiprack_plural": "移液器吸嘴应位于{{tiprack_name}}第一列正上方并居中对齐,并且与吸头顶部水平对齐。", "labware_step_detail_tiprack": "移液器吸嘴应居中于{{tiprack_name}}的A1位置上方,并且与吸头顶部水平对齐。", - "labware": "耗材", + "labware_step_detail_tiprack_plural": "移液器吸嘴应位于{{tiprack_name}}第一列正上方并居中对齐,并且与吸头顶部水平对齐。", "learn_more": "了解更多", "location": "位置", "lpc_complete_summary_screen_heading": "耗材位置校准完成", @@ -73,9 +73,9 @@ "new_labware_offset_data": "新的耗材校准数据", "ninety_six_probe_location": "A1(左上角)", "no_labware_offsets": "无耗材校准数据", + "no_offset_data": "没有可用的校准数据", "no_offset_data_available": "没有可用的耗材校准数据", "no_offset_data_on_robot": "这轮运行中此工作站没有可用的耗材校准数据。", - "no_offset_data": "没有可用的校准数据", "offsets": "校准数据", "pick_up_tip_from_rack_in_location": "从位于{{location}}的吸头盒上拾取吸头", "picking_up_tip_title": "在板位{{slot}}拾取吸头", @@ -98,13 +98,13 @@ "robot_has_no_offsets_from_previous_runs": "耗材校准数据引用自之前运行的协议,以节省您的时间。如果本协议中的所有耗材已在之前的运行中检查过,这些数据将应用于本次运行。 您可以在后面的步骤中使用耗材位置校准添加新的偏移量。", "robot_has_offsets_from_previous_runs": "此工作站具有本协议中所用耗材的校准数据。如果您应用了这些校准数据,仍可通过耗材位置校准程序进行调整。", "robot_in_motion": "工作站正在运行,请远离。", - "run_labware_position_check": "运行耗材位置校准程序", "run": "运行", + "run_labware_position_check": "运行耗材位置校准程序", "secondary_pipette_tipracks_section": "使用{{secondary_mount}}移液器检查吸头盒", "see_how_offsets_work": "了解耗材校准的工作原理", + "slot": "板位{{slotName}}", "slot_location": "板位位置", "slot_name": "板位{{slotName}}", - "slot": "板位{{slotName}}", "start_position_check": "开始耗材位置校准程序,移至板位{{initial_labware_slot}}", "stored_offset_data": "应用已存储的耗材校准数据?", "stored_offsets_for_this_protocol": "适用于本协议的已存储耗材校准数据", diff --git a/app/src/assets/localization/zh/module_wizard_flows.json b/app/src/assets/localization/zh/module_wizard_flows.json index b1cd0b086d6..c2d6af09862 100644 --- a/app/src/assets/localization/zh/module_wizard_flows.json +++ b/app/src/assets/localization/zh/module_wizard_flows.json @@ -1,21 +1,21 @@ { "attach_probe": "将校准探头安装到移液器", "begin_calibration": "开始校准", - "calibrate_pipette": "在进行模块校准之前,请先校准移液器", "calibrate": "校准", + "calibrate_pipette": "在进行模块校准之前,请先校准移液器", + "calibration": "{{module}}校准", "calibration_adapter_heatershaker": "校准适配器", "calibration_adapter_temperature": "校准适配器", "calibration_adapter_thermocycler": "校准适配器", - "calibration_probe_touching_thermocycler": "校准探头将接触探测热循环仪的校准方块,以确定其确切位置", - "calibration_probe_touching": "校准探头将接触探测{{slotNumber}}板位中{{module}}的校准方块,以确定其确切位置", "calibration_probe": "从存储位置取出校准探头,将探头的锁套旋钮按顺时针方向拧松。对准图示位置,将校准探头向上轻推并压到顶部。随后将锁套旋钮按逆时针方向拧紧,并轻拉确认是否固定稳妥。", - "calibration": "{{module}}校准", + "calibration_probe_touching": "校准探头将接触探测{{slotNumber}}板位中{{module}}的校准方块,以确定其确切位置", + "calibration_probe_touching_thermocycler": "校准探头将接触探测热循环仪的校准方块,以确定其确切位置", "checking_firmware": "检查{{module}}固件", "complete_calibration": "完成校准", "confirm_location": "确认位置", "confirm_placement": "确认已放置", - "detach_probe_description": "解锁校准探头,将其从吸嘴上卸下并放回原储存位置。", "detach_probe": "卸下移液器校准探头", + "detach_probe_description": "解锁校准探头,将其从吸嘴上卸下并放回原储存位置。", "error_during_calibration": "校准过程中出现错误", "error_prepping_module": "模块校准出错", "exit": "退出", @@ -32,16 +32,16 @@ "move_gantry_to_front": "将龙门架移至前端", "next": "下一步", "pipette_probe": "移液器校准探头", + "place_flush": "将适配器水平放到模块上。", "place_flush_heater_shaker": "将适配器水平放到模块上。使用热震荡模块专用螺丝和 T10 Torx 螺丝刀将适配器固定到模块上。", "place_flush_thermocycler": "确保热循环仪盖子已打开,并将适配器水平放置到模块上,即通常放置pcr板的位置。", - "place_flush": "将适配器水平放到模块上。", "prepping_module": "正在准备{{module}}进行模块校准", "recalibrate": "重新校准", "select_location": "选择模块放置位置", "select_the_slot": "请在右侧的甲板图中选择放置了{{module}}的板位。请确认所选择位置的正确性以确保顺利完成校准。", "slot_unavailable": "板位不可用", - "stand_back_robot_in_motion": "工作站正在运行,请远离", "stand_back": "正在进行校准,请远离", + "stand_back_robot_in_motion": "工作站正在运行,请远离", "start_setup": "开始设置", "successfully_calibrated": "{{module}}已成功校准" } diff --git a/app/src/assets/localization/zh/pipette_wizard_flows.json b/app/src/assets/localization/zh/pipette_wizard_flows.json index 1e75fe6223d..a1bec2143bb 100644 --- a/app/src/assets/localization/zh/pipette_wizard_flows.json +++ b/app/src/assets/localization/zh/pipette_wizard_flows.json @@ -2,14 +2,14 @@ "align_the_connector": "对准对接孔,将移液器安装到工作站上。使用六角螺丝刀拧紧螺丝以固定移液器。然后手动检查其是否已完全固定。", "all_pipette_detached": "所有移液器已成功卸下", "are_you_sure_exit": "您确定要在完成{{flow}}之前退出吗?", - "attach_96_channel_plus_detach": "卸下{{pipetteName}}并安装96通道移液器", + "attach": "正在安装移液器", "attach_96_channel": "安装96通道移液器", - "attach_mounting_plate_instructions": "对准对接孔,将移液器安装到工作站上。为了准确对齐,您可能需要调整右侧移液器支架的位置。", + "attach_96_channel_plus_detach": "卸下{{pipetteName}}并安装96通道移液器", "attach_mounting_plate": "安装固定板", + "attach_mounting_plate_instructions": "对准对接孔,将移液器安装到工作站上。为了准确对齐,您可能需要调整右侧移液器支架的位置。", "attach_pip": "安装移液器", "attach_pipette": "安装{{mount}}移液器", "attach_probe": "安装校准探头", - "attach": "正在安装移液器", "backmost": "最后面的", "before_you_begin": "开始之前", "begin_calibration": "开始校准", @@ -25,6 +25,7 @@ "connect_and_secure_pipette": "连接并固定移液器", "continue": "继续", "critical_unskippable_step": "这是关键步骤,不应跳过", + "detach": "正在卸下移液器", "detach_96_attach_mount": "卸下96通道移液器并安装{{mount}}移液器", "detach_96_channel": "卸下96通道移液器", "detach_and_reattach": "卸下并重新安装移液器", @@ -32,14 +33,13 @@ "detach_mount_attach_96": "卸下{{mount}}移液器并安装96通道移液器", "detach_mounting_plate_instructions": "抓住板子,防止其掉落。拧开移液器固定板的销钉。", "detach_next_pipette": "卸下下一个移液器", - "detach_pipette_to_attach_96": "卸下{{pipetteName}}并安装96通道移液器", "detach_pipette": "卸下{{mount}}移液器", + "detach_pipette_to_attach_96": "卸下{{pipetteName}}并安装96通道移液器", "detach_pipettes_attach_96": "卸下移液器并安装96通道移液器", "detach_z_axis_screw_again": "在安装96通道移液器前,先拧开Z轴螺丝。", - "detach": "正在卸下移液器", "exit_cal": "退出校准", - "firmware_updating": "需要固件更新,仪器正在更新中...", "firmware_up_to_date": "已是最新版本。", + "firmware_updating": "需要固件更新,仪器正在更新中...", "gantry_empty_for_96_channel_success": "现在两个移液器支架都为空,您可以开始进行96通道移液器的安装。", "get_started_detach": "开始前,请移除甲板上的实验耗材,清理工作区以便卸载。同时准备好屏幕所示的所需设备。", "grab_screwdriver": "保持原位不动,用2.5毫米螺丝刀,按照引导动画所示拧紧螺丝。在继续操作前,手动测试移液器安装和固定情况。", @@ -67,11 +67,12 @@ "pipette_heavy": "96通道移液器较重({{weight}})。如有需要,可以请其他人员帮忙。", "please_install_correct_pip": "请改用{{pipetteName}}", "progress_will_be_lost": "{{flow}}的进度将会丢失", + "provided_with_robot": "随工作站提供。使用其他尺寸的工具可能会损坏机器的螺丝。", "reattach_carriage": "重新连接Z轴板", "recalibrate_pipette": "重新校准{{mount}}移液器", "remove_cal_probe": "移除校准探头", - "remove_labware_to_get_started": "开始前,请清除甲板上的实验耗材,清理工作区,以便校准。同时收集屏幕显示的所需设备。校准探头随工作站提供,应存放在工作站的右前方支柱上。", "remove_labware": "开始前,请清除甲板上的实验耗材,清理工作区,以便校准。同时收集屏幕显示的所需设备。校准探头随工作站提供,应存放在工作站的右前方支柱上。", + "remove_labware_to_get_started": "开始前,请清除甲板上的实验耗材,清理工作区,以便校准。同时收集屏幕显示的所需设备。校准探头随工作站提供,应存放在工作站的右前方支柱上。", "remove_probe": "拧松校准探头,将其从喷嘴上拆下,并放回存储位置。", "replace_pipette": "更换{{mount}}移液器", "return_probe_error": "退出前,请将校准探头放回其存放位置。 {{error}}", diff --git a/app/src/assets/localization/zh/protocol_command_text.json b/app/src/assets/localization/zh/protocol_command_text.json index 9d976c2bc88..a32a79e70b5 100644 --- a/app/src/assets/localization/zh/protocol_command_text.json +++ b/app/src/assets/localization/zh/protocol_command_text.json @@ -1,11 +1,18 @@ { + "absorbance_reader_close_lid": "正在关闭吸光度读数器盖子", + "absorbance_reader_initialize": "正在初始化吸光度读数器,以便在{{wavelengths}}波长下执行{{mode}}测量", + "absorbance_reader_open_lid": "正在打开吸光度读数器盖子", + "absorbance_reader_read": "正在吸光度读数器中读取微孔板", "adapter_in_mod_in_slot": "{{adapter}}在{{slot}}的{{module}}上", "adapter_in_slot": "{{adapter}}在{{slot}}上", + "air_gap_in_place": "正在形成 {{volume}} µL 的空气间隙", + "all_nozzles": "所有移液喷嘴", "aspirate": "从{{labware_location}}的{{labware}}的{{well_name}}孔中以{{flow_rate}}µL/秒的速度吸液{{volume}}µL", "aspirate_in_place": "在原位以{{flow_rate}}µL/秒的速度吸液{{volume}}µL", "blowout": "在{{labware_location}}的{{labware}}的{{well_name}}孔中以{{flow_rate}}µL/秒的速度排空", "blowout_in_place": "在原位以{{flow_rate}}µL/秒的速度排空", "closing_tc_lid": "关闭热循环仪热盖", + "column_layout": "列布局", "comment": "解释", "configure_for_volume": "配置{{pipette}}以吸液{{volume}}µL", "configure_nozzle_layout": "配置{{pipette}}以使用{{amount}}个通道", @@ -18,55 +25,67 @@ "degrees_c": "{{temp}}°C", "detect_liquid_presence": "正在检测{{labware}}在{{labware_location}}中的{{well_name}}孔中的液体存在", "disengaging_magnetic_module": "下降磁力架模块", - "dispense_push_out": "以{{flow_rate}}µL/秒的速度将{{volume}}µL 排液至{{labware_location}}的{{labware}}的{{well_name}}孔中,并推出{{push_out_volume}}µL", "dispense": "以{{flow_rate}}µL/秒的速度将{{volume}}µL 排液至{{labware_location}}的{{labware}}的{{well_name}}孔中", "dispense_in_place": "在原位以{{flow_rate}}µL/秒的速度排液{{volume}}µL", + "dispense_push_out": "以{{flow_rate}}µL/秒的速度将{{volume}}µL 排液至{{labware_location}}的{{labware}}的{{well_name}}孔中,并推出{{push_out_volume}}µL", "drop_tip": "将吸头丢入{{labware}}的{{well_name}}孔中", "drop_tip_in_place": "在原位丢弃吸头", + "dropping_tip_in_trash": "将吸头丢入{{trash}}", "engaging_magnetic_module": "抬升磁力架模块", "fixed_trash": "垃圾桶", "home_gantry": "复位所有龙门架、移液器和柱塞轴", + "in_location": "在{{location}}", "latching_hs_latch": "在热震荡模块上锁定实验耗材", "left": "左", + "load_labware_to_display_location": "{{display_location}}加载{{labware}}", "load_liquids_info_protocol_setup": "将{{liquid}}加载到{{labware}}中", "load_module_protocol_setup": "在甲板槽{{slot_name}}中加载模块{{module}}", "load_pipette_protocol_setup": "在{{mount_name}}支架上加载{{pipette_name}}", - "module_in_slot_plural": "{{module}}", "module_in_slot": "{{module}}在{{slot_name}}号板位", + "module_in_slot_plural": "{{module}}", + "move_labware": "移动实验耗材", "move_labware_manually": "手动将{{labware}}从{{old_location}}移动到{{new_location}}", "move_labware_on": "在{{robot_name}}上移动实验耗材", "move_labware_using_gripper": "使用转板抓手将{{labware}}从{{old_location}}移动到{{new_location}}", - "move_labware": "移动实验耗材", "move_relative": "沿{{axis}}轴移动{{distance}}毫米", + "move_to_addressable_area": "移动到{{addressable_area}}", + "move_to_addressable_area_drop_tip": "移动到{{addressable_area}}", "move_to_coordinates": "移动到 (X:{{x}}, Y:{{y}}, Z:{{z}})", "move_to_slot": "移动到{{slot_name}}号板位", "move_to_well": "移动到{{labware_location}}的{{labware}}的{{well_name}}孔", - "move_to_addressable_area": "移动到{{addressable_area}}", - "move_to_addressable_area_drop_tip": "移动到{{addressable_area}}", + "multiple": "多个", "notes": "备注", "off_deck": "甲板外", "offdeck": "甲板外", + "on_location": "在{{location}}", "opening_tc_lid": "打开热循环仪热盖", - "pause_on": "在{{robot_name}}上暂停", + "partial_layout": "部分布局", "pause": "暂停", + "pause_on": "在{{robot_name}}上暂停", "pickup_tip": "从{{labware_location}}的{{labware}}的{{well_range}}孔中拾取吸头", "prepare_to_aspirate": "准备使用{{pipette}}吸液", "reloading_labware": "正在重新加载{{labware}}", "return_tip": "将吸头返回到{{labware_location}}的{{labware}}的{{well_name}}孔中", "right": "右", + "row_layout": "行布局", "save_position": "保存位置", "set_and_await_hs_shake": "设置热震荡模块以{{rpm}}rpm 震动并等待达到该转速", "setting_hs_temp": "将热震荡模块的目标温度设置为{{temp}}", "setting_temperature_module_temp": "将温控模块设置为{{temp}}(四舍五入到最接近的整数)", "setting_thermocycler_block_temp": "将热循环仪加热块温度设置为{{temp}},并在达到目标后保持{{hold_time_seconds}}秒", "setting_thermocycler_lid_temp": "将热循环仪热盖温度设置为{{temp}}", + "single": "单个", + "single_nozzle_layout": "单个移液喷嘴布局", "slot": "板位{{slot_name}}", "target_temperature": "目标温度", "tc_awaiting_for_duration": "等待热循环仪程序完成", "tc_run_profile_steps": "温度:{{celsius}}°C,时间:{{seconds}}秒", + "tc_starting_extended_profile": "运行热循环仪程序,共有{{elementCount}}个步骤和循环:", + "tc_starting_extended_profile_cycle": "以下步骤重复{{repetitions}}次:", "tc_starting_profile": "热循环仪开始进行由以下步骤组成的{{repetitions}}次循环:", - "trash_bin_in_slot": "垃圾桶在{{slot_name}}", "touch_tip": "吸头接触内壁", + "trash_bin": "垃圾桶", + "trash_bin_in_slot": "垃圾桶在{{slot_name}}", "turning_rail_lights_off": "正在关闭导轨灯", "turning_rail_lights_on": "正在打开导轨灯", "unlatching_hs_latch": "解锁热震荡模块上的实验耗材", @@ -76,5 +95,6 @@ "waiting_for_tc_block_to_reach": "等待热循环仪加热块达到目标温度并保持指定时间", "waiting_for_tc_lid_to_reach": "等待热循环仪热盖达到目标温度", "waiting_to_reach_temp_module": "等待温控模块达到{{temp}}", - "waste_chute": "外置垃圾槽" + "waste_chute": "外置垃圾槽", + "with_reference_of": "以{{wavelength}} nm为基准" } diff --git a/app/src/assets/localization/zh/protocol_details.json b/app/src/assets/localization/zh/protocol_details.json index 22f4c0566fc..3bb53fe43c5 100644 --- a/app/src/assets/localization/zh/protocol_details.json +++ b/app/src/assets/localization/zh/protocol_details.json @@ -10,32 +10,31 @@ "connected": "已连接", "connection_status": "连接状态", "creation_method": "创建方法", - "csv_file_type_required": "需要CSV文件类型", "csv_file": "CSV文件", - "csv_required": "该协议需要CSV文件才能继续。", + "csv_file_type_required": "需要CSV文件类型", "deck_view": "甲板视图", "default_value": "默认值", - "delete_protocol_perm": "{{name}}及其运行历史将被永久删除。", "delete_protocol": "删除协议", + "delete_protocol_perm": "{{name}}及其运行历史将被永久删除。", "delete_this_protocol": "删除此协议?", "description": "描述", "extension_mount": "扩展安装支架", "file_required": "需要文件", "go_to_labware_definition": "转到实验耗材定义", "go_to_timeline": "转到时间线", - "gripper_pick_up_count_description": "使用转板抓手移动单个耗材的指令。", "gripper_pick_up_count": "转板次数", + "gripper_pick_up_count_description": "使用转板抓手移动单个耗材的指令。", "hardware": "硬件", - "labware_name": "耗材名称", "labware": "耗材", + "labware_name": "耗材名称", "last_analyzed": "上一次分析", "last_updated": "上一次更新", "left_and_right_mounts": "左+右安装架", "left_mount": "左移液器安装位", "left_right": "左,右", "liquid_name": "液体名称", - "liquids_not_in_protocol": "此协议未指定任何液体", "liquids": "液体", + "liquids_not_in_protocol": "此协议未指定任何液体", "listed_values_are_view_only": "列出的值仅供查看", "location": "位置", "modules": "模块", @@ -51,16 +50,16 @@ "num_choices": "{{num}}个选择", "num_options": "{{num}}个选项", "off": "关闭", - "on_off": "开,关", "on": "开启", + "on_off": "开,关", "org_or_author": "组织/作者", "parameters": "参数", - "pipette_aspirate_count_description": "每个移液器的单个吸液指令。", "pipette_aspirate_count": "{{pipette}}吸液次数", - "pipette_dispense_count_description": "每个移液器的单个排液指令。", + "pipette_aspirate_count_description": "每个移液器的单个吸液指令。", "pipette_dispense_count": "{{pipette}}分液次数", - "pipette_pick_up_count_description": "每个移液器的单个拾取吸头指令。", + "pipette_dispense_count_description": "每个移液器的单个排液指令。", "pipette_pick_up_count": "{{pipette}}拾取吸头次数", + "pipette_pick_up_count_description": "每个移液器的单个拾取吸头指令。", "proceed_to_setup": "继续进行设置", "protocol_designer_version": "在线协议编辑器{{version}}", "protocol_failed_app_analysis": "该协议在应用程序内分析失败。它可能在没有自定义软件配置的工作站上无法使用。", @@ -74,24 +73,24 @@ "requires_upload": "需要上传", "restore_defaults": "恢复默认值", "right_mount": "右移液器安装位", + "robot": "工作站", "robot_configuration": "工作站配置", - "robot_is_busy_with_protocol": "{{robotName}}正在运行{{protocolName}},状态为{{runStatus}}。是否要清除并继续?", "robot_is_busy": "{{robotName}}正在工作", - "robot": "工作站", + "robot_is_busy_with_protocol": "{{robotName}}正在运行{{protocolName}},状态为{{runStatus}}。是否要清除并继续?", "run_protocol": "运行协议", "select_parameters_for_robot": "选择{{robot_name}}的参数", "send": "发送", "sending": "发送中", "show_in_folder": "在文件夹中显示", "slot": "{{slotName}}号板位", - "start_setup_customize_values": "开始设置以自定义值", "start_setup": "开始设置", + "start_setup_customize_values": "开始设置以自定义值", "successfully_sent": "发送成功", "total_volume": "总体积", - "unavailable_or_busy_robot_not_listed_plural": "{{count}}台不可用或工作中的工作站未列出。", "unavailable_or_busy_robot_not_listed": "{{count}}台不可用或工作中的工作站未列出。", - "unavailable_robot_not_listed_plural": "{{count}}台不可用的工作站未列出。", + "unavailable_or_busy_robot_not_listed_plural": "{{count}}台不可用或工作中的工作站未列出。", "unavailable_robot_not_listed": "{{count}}台不可用的工作站未列出。.", + "unavailable_robot_not_listed_plural": "{{count}}台不可用的工作站未列出。", "unsuccessfully_sent": "发送失败", "value_out_of_range": "值必须在{{min}}-{{max}}之间", "view_run_details": "查看运行详情", diff --git a/app/src/assets/localization/zh/protocol_info.json b/app/src/assets/localization/zh/protocol_info.json index 073b4fd6319..0654a1134cd 100644 --- a/app/src/assets/localization/zh/protocol_info.json +++ b/app/src/assets/localization/zh/protocol_info.json @@ -10,6 +10,7 @@ "creation_method": "创建方法", "custom_labware_not_supported": "工作站不支持自定义耗材", "date_added": "添加日期", + "date_added_date": "添加日期:{{date}}", "delete_protocol": "删除协议", "description": "描述", "drag_file_here": "将协议文件拖放到此处", @@ -22,9 +23,9 @@ "exit_modal_heading": "确认关闭协议", "failed_analysis": "分析失败", "get_labware_offset_data": "获取耗材校准数据", + "import": "导入", "import_a_file": "导入协议以开始", "import_new_protocol": "导入协议", - "import": "导入", "incompatible_file_type": "不兼容的文件类型", "instrument_cal_data_title": "校准数据", "instrument_not_attached": "未连接", @@ -37,10 +38,11 @@ "labware_offset_data_title": "耗材校准数据", "labware_offsets_info": "{{number}}组耗材校准数据", "labware_position_check_complete_toast_no_offsets": "耗材位置校准完成。无新建的耗材校准数据。", - "labware_position_check_complete_toast_with_offsets_plural": "耗材位置校准完成。新建了{{count}}组耗材校准数据。", "labware_position_check_complete_toast_with_offsets": "耗材位置校准完成。创建了{{count}}组耗材校准数据。", + "labware_position_check_complete_toast_with_offsets_plural": "耗材位置校准完成。新建了{{count}}组耗材校准数据。", "labware_title": "所需耗材", "last_run": "上次运行", + "last_run_time": "上次运行时间:{{time}}", "last_updated": "最近更新", "launch_protocol_designer": "打开在线协议编辑器", "manual_steps_learn_more": "了解更多关于手动步骤的信息", diff --git a/app/src/assets/localization/zh/protocol_list.json b/app/src/assets/localization/zh/protocol_list.json index 9c2b3be0f59..bb931b9e39d 100644 --- a/app/src/assets/localization/zh/protocol_list.json +++ b/app/src/assets/localization/zh/protocol_list.json @@ -16,8 +16,8 @@ "reanalyze_to_view": " 重新分析 协议", "right_mount": "右移液器安装位", "robot": "工作站", - "send_to_robot_overflow": "发送到{{robot_display_name}}", "send_to_robot": "将协议发送到{{robot_display_name}}", + "send_to_robot_overflow": "发送到{{robot_display_name}}", "show_in_folder": "在文件夹中显示", "start_setup": "开始设置", "this_protocol_will_be_trashed": "该协议将被移至此计算机的回收站,可能无法恢复。", diff --git a/app/src/assets/localization/zh/protocol_setup.json b/app/src/assets/localization/zh/protocol_setup.json index 40a5c8c00f9..990fe911f5f 100644 --- a/app/src/assets/localization/zh/protocol_setup.json +++ b/app/src/assets/localization/zh/protocol_setup.json @@ -1,8 +1,8 @@ { "96_mount": "左+右移液器安装位", "action_needed": "需要操作", - "adapter_slot_location_module": "{{slotName}}号板位,{{adapterName}}在{{moduleName}}上", "adapter_slot_location": "{{slotName}}号板位,{{adapterName}}", + "adapter_slot_location_module": "{{slotName}}号板位,{{adapterName}}在{{moduleName}}上", "add_fixture": "将{{fixtureName}}添加到{{locationName}}", "add_this_deck_hardware": "将此硬件添加到您的甲板配置中。它将在协议分析期间被引用。", "add_to_slot": "添加到{{slotName}}号板位", @@ -12,17 +12,18 @@ "applied_labware_offset_data": "已应用的实验耗材偏移数据", "applied_labware_offsets": "已应用的实验耗材偏移", "are_you_sure_you_want_to_proceed": "您确定要继续运行吗?", - "attach_gripper_failure_reason": "连接所需的转板抓手以继续", + "attach": "连接", "attach_gripper": "连接转板抓手", + "attach_gripper_failure_reason": "连接所需的转板抓手以继续", "attach_module": "校准前连接模块", "attach_pipette_before_module_calibration": "在进行模块校准前连接移液器", "attach_pipette_calibration": "连接移液器以查看校准信息", "attach_pipette_cta": "连接移液器", "attach_pipette_failure_reason": "连接所需的移液器以继续", "attach_pipette_tip_length_calibration": "连接移液器以查看吸头长度校准信息", - "attach": "连接", "back_to_top": "回到顶部", "cal_all_pip": "首先校准移液器", + "calibrate": "校准", "calibrate_deck_failure_reason": "校准甲板以继续", "calibrate_deck_to_proceed_to_pipette_calibration": "校准甲板以继续进行移液器校准", "calibrate_deck_to_proceed_to_tip_length_calibration": "校准甲板以继续进行吸头长度校准", @@ -32,16 +33,15 @@ "calibrate_pipette_before_module_calibration": "在进行模块校准前校准移液器", "calibrate_pipette_failure_reason": "校准所需的移液器以继续", "calibrate_tiprack_failure_reason": "校准所需的吸头长度以继续", - "calibrate": "校准", "calibrated": "已校准", + "calibration": "校准", "calibration_data_not_available": "一旦运行开始,校准数据不可用", "calibration_needed": "需要校准", "calibration_ready": "校准就绪", + "calibration_required": "需要校准", "calibration_required_attach_pipette_first": "需要校准,请先连接移液器", "calibration_required_calibrate_pipette_first": "需要校准,请先校准移液器", - "calibration_required": "需要校准", "calibration_status": "校准状态", - "calibration": "校准", "cancel_and_restart_to_edit": "取消运行并重新启动设置以进行编辑", "choose_csv_file": "选择CSV文件", "choose_enum": "选择{{displayName}}", @@ -62,21 +62,21 @@ "connect_modules_for_controls": "连接模块以查看控制", "connection_info_not_available": "一旦运行开始,连接信息不可用", "connection_status": "连接状态", + "csv_file": "CSV 文件", "csv_files_on_robot": "工作站上的CSV文件", "csv_files_on_usb": "USB上的CSV文件", - "csv_file": "CSV 文件", "currently_configured": "当前已配置", "currently_unavailable": "当前不可用", "custom_values": "自定义值", + "deck_cal_description": "这测量了甲板的 X 和 Y 值相对于门架的值。甲板校准是吸头长度校准和移液器偏移校准的基础。", "deck_cal_description_bullet_1": "在新工作站设置期间执行甲板校准。", "deck_cal_description_bullet_2": "如果您搬迁了工作站,请重新进行甲板校准。", - "deck_cal_description": "这测量了甲板的 X 和 Y 值相对于门架的值。甲板校准是吸头长度校准和移液器偏移校准的基础。", "deck_calibration_title": "甲板校准(Deck Calibration)", - "deck_conflict_info_thermocycler": "通过移除位置 A1 和 B1 中的固定装置来更新甲板配置。从甲板配置中移除对应装置或更新协议。", - "deck_conflict_info": "通过移除位置 {{cutout}} 中的 {{currentFixture}} 来更新甲板配置。从甲板配置中移除对应装置或更新协议。", "deck_conflict": "甲板位置冲突", - "deck_hardware_ready": "甲板硬件准备", + "deck_conflict_info": "通过移除位置 {{cutout}} 中的 {{currentFixture}} 来更新甲板配置。从甲板配置中移除对应装置或更新协议。", + "deck_conflict_info_thermocycler": "通过移除位置 A1 和 B1 中的固定装置来更新甲板配置。从甲板配置中移除对应装置或更新协议。", "deck_hardware": "甲板硬件", + "deck_hardware_ready": "甲板硬件准备", "deck_map": "甲板布局图", "default_values": "默认值", "download_files": "下载文件", @@ -86,62 +86,63 @@ "extra_attention_warning_title": "在继续运行前固定耗材和模块", "extra_module_attached": "附加额外模块", "feedback_form_link": "请告诉我们", - "fixture_name": "装置", "fixture": "装置", - "fixtures_connected_plural": "已连接{{count}}个装置", + "fixture_name": "装置", "fixtures_connected": "已连接{{count}}个装置", + "fixtures_connected_plural": "已连接{{count}}个装置", "get_labware_offset_data": "获取耗材校准数据", "hardware_missing": "缺少硬件", "heater_shaker_extra_attention": "使用闩锁控制,便于放置耗材。", "heater_shaker_labware_list_view": "要添加耗材,请使用切换键来控制闩锁", "how_offset_data_works": "耗材校准数据如何工作", "individiual_well_volume": "单个孔体积", - "initial_liquids_num_plural": "{{count}}种初始液体", "initial_liquids_num": "{{count}}种初始液体", + "initial_liquids_num_plural": "{{count}}种初始液体", "initial_location": "初始位置", + "install_modules": "安装所需的模块。", "install_modules_and_fixtures": "安装并校准所需的模块。安装所需的装置。", "install_modules_plural": "安装所需的模块。", - "install_modules": "安装所需的模块。", - "instrument_calibrations_missing_plural": "缺少{{count}}个校准", "instrument_calibrations_missing": "缺少{{count}}个校准", - "instruments_connected_plural": "已连接{{count}}个硬件", - "instruments_connected": "已连接{{count}}个硬件", + "instrument_calibrations_missing_plural": "缺少{{count}}个校准", "instruments": "硬件", - "labware_latch_instructions": "使用闩锁控制,便于放置耗材。", + "instruments_connected": "已连接{{count}}个硬件", + "instruments_connected_plural": "已连接{{count}}个硬件", + "labware": "耗材", "labware_latch": "耗材闩锁", + "labware_latch_instructions": "使用闩锁控制,便于放置耗材。", "labware_location": "耗材位置", "labware_name": "耗材名称", "labware_placement": "实验耗材放置", + "labware_position_check": "耗材位置校准", + "labware_position_check_not_available": "运行开始后,耗材位置校准不可用", "labware_position_check_not_available_analyzing_on_robot": "在工作站上分析协议时,耗材位置校准不可用", "labware_position_check_not_available_empty_protocol": "耗材位置校准需要协议加载耗材和移液器", - "labware_position_check_not_available": "运行开始后,耗材位置校准不可用", "labware_position_check_step_description": "建议的工作流程可帮助您验证每个耗材在甲板上的位置。", "labware_position_check_step_title": "耗材位置校准", "labware_position_check_text": "耗材位置校准流程可帮助您验证甲板上每个耗材的位置。在此位置校准过程中,您可以创建耗材校准数据,以调整工作站在 X、Y 和 Z 方向上的移动。", - "labware_position_check": "耗材位置校准", + "labware_quantity": "数量:{{quantity}}", "labware_setup_step_description": "准备好以下耗材和完整的吸头盒。若不进行耗材位置校准直接运行协议,请将耗材放置在其初始位置并固定。", "labware_setup_step_title": "耗材", - "labware": "耗材", "last_calibrated": "最后校准:{{date}}", "learn_how_it_works": "了解它的工作原理", + "learn_more": "了解更多", "learn_more_about_offset_data": "了解更多关于耗材校准数据的信息", "learn_more_about_robot_cal_link": "了解更多关于工作站校准的信息", - "learn_more": "了解更多", "liquid_information": "液体信息", "liquid_name": "液体名称", "liquid_setup_step_description": "查看液体的起始位置和体积", "liquid_setup_step_title": "液体", + "liquids": "液体", "liquids_confirmed": "液体已确认", "liquids_not_in_setup": "此协议未使用液体", "liquids_not_in_the_protocol": "此协议未指定液体。", "liquids_ready": "液体准备", - "liquids": "液体", "list_view": "列表视图", "loading_data": "加载数据...", "loading_labware_offsets": "加载耗材校准数据", "loading_protocol_details": "加载详情...", - "location_conflict": "位置冲突", "location": "位置", + "location_conflict": "位置冲突", "lpc_and_offset_data_title": "耗材位置校准和耗材校准数据", "lpc_disabled_calibration_not_complete": "确保工作站校准完成后再运行耗材位置校准", "lpc_disabled_modules_and_calibration_not_complete": "确保工作站校准完成并且所有模块已连接后再运行耗材位置校准", @@ -149,36 +150,37 @@ "lpc_disabled_no_tipracks_loaded": "耗材位置校准需要在协议中加载一个吸头盒", "lpc_disabled_no_tipracks_used": "耗材位置校准要求协议中至少有一个吸头可供使用", "map_view": "布局视图", + "missing": "缺少", "missing_gripper": "缺少转板抓手", "missing_instruments": "缺少{{count}}个", - "missing_pipettes_plural": "缺少{{count}}个移液器", "missing_pipettes": "缺少{{count}}个移液器", - "missing": "缺少", + "missing_pipettes_plural": "缺少{{count}}个移液器", "modal_instructions_title": "{{moduleName}}设置说明", + "module": "模块", "module_connected": "已连接", "module_disconnected": "未连接", "module_instructions_link": "{{moduleName}}设置说明", + "module_instructions_manual": "要了解有关设置模块的分步说明,请查阅包装盒内的快速入门指南。您也可以点击下面的链接或扫描二维码,查看模块使用说明书。", "module_mismatch_body": "检查连接到该工作站的模块型号是否正确", "module_name": "模块", "module_not_connected": "未连接", "module_setup_step_ready": "校准准备", "module_setup_step_title": "甲板硬件", "module_slot_location": "{{slotName}}号板位,{{moduleName}}", - "module": "模块", - "modules_connected_plural": "连接了{{count}}个模块", + "modules": "模块", "modules_connected": "连接了{{count}}个模块", + "modules_connected_plural": "连接了{{count}}个模块", "modules_setup_step_title": "模块设置", - "modules": "模块", - "mount_title": "{{mount}}安装支架:", "mount": "{{mount}}安装支架", + "mount_title": "{{mount}}安装支架:", "multiple_fixtures_missing": "缺少{{count}}个装置", + "multiple_modules": "相同类型的多个模块", "multiple_modules_example": "您的协议包含两个温控模块。连接到左侧第一个端口的温控模块对应协议中的第一个温控模块,连接到下一个端口的温控模块对应协议中的第二个温控模块。如果使用集线器,遵循相同的端口排序逻辑。", "multiple_modules_explanation": "在协议中使用多个相同类型的模块时,首先需要将协议中第一个模块连接到工作站编号最小的USB端口,然后以相同方式连接其他模块。", "multiple_modules_help_link_title": "查看如何设置相同类型的多个模块", "multiple_modules_learn_more": "了解更多关于使用相同类型的多个模块的信息", "multiple_modules_missing_plural": "缺少{{count}}个模块", "multiple_modules_modal": "设置相同类型的多个模块", - "multiple_modules": "相同类型的多个模块", "multiple_of_most_modules": "通过以特定顺序连接和加载模块,可以在单个Python协议中使用多种模块类型。无论模块占用哪个甲板板位,工作站都将首先初始化连接到最小编号端口的匹配模块,。", "must_have_labware_and_pip": "协议中必须加载耗材和移液器", "n_a": "不可用", @@ -191,8 +193,8 @@ "no_modules_or_fixtures": "该协议中未指定任何模块或装置。", "no_modules_specified": "该协议中未指定任何模块。", "no_modules_used_in_this_protocol": "该协议中未使用硬件", - "no_parameters_specified_in_protocol": "协议中未指定任何参数", "no_parameters_specified": "未指定参数", + "no_parameters_specified_in_protocol": "协议中未指定任何参数", "no_tiprack_loaded": "协议中必须加载一个吸头盒", "no_tiprack_used": "协议中必须拾取一个吸头", "no_usb_connection_required": "无需USB连接", @@ -200,33 +202,32 @@ "no_usb_required": "无需USB", "not_calibrated": "尚未校准", "not_configured": "未配置", - "off_deck": "甲板外", "off": "关闭", + "off_deck": "甲板外", "offset_data": "偏移校准数据", - "offsets_applied_plural": "应用了{{count}}个偏移校准数据", "offsets_applied": "应用了{{count}}个偏移校准数据", "offsets_confirmed": "偏移校准数据已确认", "offsets_ready": "偏移校准数据准备", - "on_adapter_in_mod": "在{{moduleName}}中的{{adapterName}}上", + "on": "开启", + "on-deck_labware": "{{count}}个在甲板上的耗材", "on_adapter": "在{{adapterName}}上", + "on_adapter_in_mod": "在{{moduleName}}中的{{adapterName}}上", "on_deck": "在甲板上", - "on-deck_labware": "{{count}}个在甲板上的耗材", - "on": "开启", "opening": "打开中...", "parameters": "参数", "pipette_mismatch": "移液器型号不匹配。", "pipette_missing": "移液器缺失", + "pipette_offset_cal": "移液器偏移校准", + "pipette_offset_cal_description": "这会测量移液器相对于移液器安装支架和甲板的X、Y和Z值。移液器偏移校准依赖于甲板校准和吸头长度校准。 ", "pipette_offset_cal_description_bullet_1": "首次将移液器连接到新安装支架时执行移液器偏移校准。", "pipette_offset_cal_description_bullet_2": "在执行甲板校准后重新进行移液器偏移校准。", "pipette_offset_cal_description_bullet_3": "对用于校准移液器的吸头执行吸头长度校准后,重新进行移液器偏移校准。", - "pipette_offset_cal_description": "这会测量移液器相对于移液器安装支架和甲板的X、Y和Z值。移液器偏移校准依赖于甲板校准和吸头长度校准。 ", - "pipette_offset_cal": "移液器偏移校准", + "placement": "放置", "placements_confirmed": "位置已确认", "placements_ready": "位置准备", - "placement": "放置", "plug_in_module_to_configure": "插入{{module}}以将其添加到板位", - "plug_in_required_module_plural": "插入并启动所需模块以继续", "plug_in_required_module": "插入并启动所需模块以继续", + "plug_in_required_module_plural": "插入并启动所需模块以继续", "prepare_to_run": "准备运行", "proceed_to_labware_position_check": "继续进行耗材位置校准", "proceed_to_labware_setup_step": "继续进行耗材设置", @@ -248,34 +249,34 @@ "recalibrating_not_available": "无法重新进行吸头长度校准和耗材位置校准。", "recalibrating_tip_length_not_available": "运行开始后无法重新校准吸头长度", "recommended": "推荐", - "required_instrument_calibrations": "所需的硬件校准", "required": "必需", + "required_instrument_calibrations": "所需的硬件校准", "required_tip_racks_title": "所需的吸头长度校准", - "reset_parameter_values_body": "这将丢弃您所做的任何更改。所有参数将恢复默认值。", "reset_parameter_values": "重置参数值?", + "reset_parameter_values_body": "这将丢弃您所做的任何更改。所有参数将恢复默认值。", "reset_setup": "重新开始设置以进行编辑", "reset_values": "重置值", "resolve": "解决", - "restart_setup_and_try": "重新开始设置并尝试使用不同的参数值。", "restart_setup": "重新开始设置", + "restart_setup_and_try": "重新开始设置并尝试使用不同的参数值。", "restore_default": "恢复默认值", "restore_defaults": "恢复默认值", "robot_cal_description": "工作站校准用于确定其相对于甲板的位置。良好的工作站校准对于成功运行协议至关重要。工作站校准包括3个部分:甲板校准、吸头长度校准和移液器偏移校准。", "robot_cal_help_title": "工作站校准的工作原理", - "robot_calibration_step_description_pipettes_only": "查看该协议所需的硬件和校准。", "robot_calibration_step_description": "查看该协议所需的移液器和吸头长度校准。", + "robot_calibration_step_description_pipettes_only": "查看该协议所需的硬件和校准。", "robot_calibration_step_ready": "校准准备", "robot_calibration_step_title": "硬件", + "run": "运行", "run_disabled_calibration_not_complete": "确保工作站校准完成后再继续运行", "run_disabled_modules_and_calibration_not_complete": "确保工作站校准完成并且所有模块已连接后再继续运行", "run_disabled_modules_not_connected": "确保所有模块已连接后再继续运行", - "run_labware_position_check_to_get_offsets": "运行实验室位置检查以获取实验室偏移数据。", "run_labware_position_check": "运行耗材位置校准", + "run_labware_position_check_to_get_offsets": "运行实验室位置检查以获取实验室偏移数据。", "run_never_started": "运行未开始", - "run": "运行", + "secure": "固定", "secure_labware_instructions": "固定耗材说明", "secure_labware_modal": "将耗材固定到{{name}}", - "secure": "固定", "setup_for_run": "运行设置", "setup_instructions": "设置说明", "setup_is_view_only": "运行开始后设置仅供查看", @@ -287,22 +288,22 @@ "step": "步骤{{index}}", "there_are_no_unconfigured_modules": "没有连接{{module}}。请连接一个模块并放置在{{slot}}号板位中。", "there_are_other_configured_modules": "已有一个{{module}}配置在不同的板位中。退出运行设置,并更新甲板配置以转到已连接的模块。或连接另一个{{module}}继续设置。", - "tip_length_cal_description_bullet": "对移液器上将会用到的每种类型的吸头执行吸头长度校准。", "tip_length_cal_description": "这将测量吸头底部与移液器喷嘴之间的Z轴距离。如果对用于校准移液器的吸头重新进行吸头长度校准,也需要重新进行移液器偏移校准。", + "tip_length_cal_description_bullet": "对移液器上将会用到的每种类型的吸头执行吸头长度校准。", "tip_length_cal_title": "吸头长度校准", "tip_length_calibration": "吸头长度校准", "total_liquid_volume": "总体积", - "update_deck_config": "更新甲板配置", "update_deck": "更新甲板", + "update_deck_config": "更新甲板配置", "update_offsets": "更新偏移校准数据", "updated": "已更新", "usb_connected_no_port_info": "USB端口已连接", "usb_drive_notification": "在运行开始前,请保持USB处于连接状态", "usb_port_connected": "USB端口{{port}}", "usb_port_number": "USB-{{port}}", - "value_out_of_range_generic": "值必须在范围内", - "value_out_of_range": "值必须在{{min}}-{{max}}之间", "value": "值", + "value_out_of_range": "值必须在{{min}}-{{max}}之间", + "value_out_of_range_generic": "值必须在范围内", "values_are_view_only": "值仅供查看", "variable_well_amount": "可变孔数", "view_current_offsets": "查看当前偏移量", diff --git a/app/src/assets/localization/zh/quick_transfer.json b/app/src/assets/localization/zh/quick_transfer.json index 5ecce11bb9c..159b627daf4 100644 --- a/app/src/assets/localization/zh/quick_transfer.json +++ b/app/src/assets/localization/zh/quick_transfer.json @@ -1,23 +1,25 @@ { "a_way_to_move_liquid": "一种将单一液体从一个实验耗材移动到另一个实验耗材的方法。", - "add_or_remove_columns": "添加或移除列", "add_or_remove": "添加或移除", + "add_or_remove_columns": "添加或移除列", "advanced_setting_disabled": "此移液的高级设置已禁用", "advanced_settings": "高级设置", + "air_gap": "空气间隙", + "air_gap_after_aspirating": "吸液后形成空气间隙", "air_gap_before_dispensing": "在分液前设置空气间隙", "air_gap_capacity_error": "移液器空间已满,无法添加空气间隙。", "air_gap_value": "{{volume}} µL", "air_gap_volume_µL": "空气间隙体积(µL)", - "air_gap": "空气间隙", "all": "所有实验耗材", "always": "每次吸液前", - "aspirate_flow_rate_µL": "吸取流速(µL/s)", "aspirate_flow_rate": "吸取流速", + "aspirate_flow_rate_µL": "吸取流速(µL/s)", "aspirate_settings": "吸取设置", "aspirate_tip_position": "吸取移液器位置", "aspirate_volume": "每孔吸液体积", "aspirate_volume_µL": "每孔吸液体积(µL)", "attach_pipette": "连接移液器", + "blow_out": "吹出", "blow_out_after_dispensing": "分液后吹出", "blow_out_destination_well": "目标孔", "blow_out_into_destination_well": "到目标孔", @@ -27,7 +29,6 @@ "blow_out_source_well": "源孔", "blow_out_trash_bin": "垃圾桶", "blow_out_waste_chute": "外置垃圾槽", - "blow_out": "吹出", "both_mounts": "左侧+右侧支架", "change_tip": "更换吸头", "character_limit_error": "字数超出限制", @@ -38,23 +39,24 @@ "create_new_transfer": "创建新的快速移液命令", "create_to_get_started": "创建新的快速移液以开始操作。", "create_transfer": "创建移液命令", + "delay": "延迟", + "delay_after_aspirating": "吸液后延迟", "delay_before_dispensing": "分液前的延迟", "delay_duration_s": "延迟时长(秒)", "delay_position_mm": "距孔底延迟时的位置(mm)", "delay_value": "{{delay}}秒,距离孔底{{position}}mm", - "delay": "延迟", "delete_this_transfer": "确定删除此这个快速移液?", "delete_transfer": "删除快速移液", "deleted_transfer": "已删除快速移液", "destination": "目标", "destination_labware": "目标实验耗材", "disabled": "已禁用", - "dispense_flow_rate_µL": "分液流速(µL/s)", "dispense_flow_rate": "分液流速", + "dispense_flow_rate_µL": "分液流速(µL/s)", "dispense_settings": "分液设置", "dispense_tip_position": "分液吸头位置", - "dispense_volume_µL": "每孔排液体积(µL)", "dispense_volume": "每孔排液体积", + "dispense_volume_µL": "每孔排液体积(µL)", "disposal_volume_µL": "废液量(µL)", "distance_bottom_of_well_mm": "距离孔底的高度(mm)", "distribute_volume_error": "所选源孔太小,无法从中分液。请尝试向更少的孔中分液。", @@ -70,12 +72,12 @@ "learn_more": "了解更多", "left_mount": "左侧支架", "lose_all_progress": "您将失去所有此快速移液流程进度.", + "mix": "混匀", "mix_before_aspirating": "在吸液前混匀", "mix_before_dispensing": "在分液前混匀", "mix_repetitions": "混匀重复次数", "mix_value": "{{volume}} µL,混匀{{reps}}次", "mix_volume_µL": "混匀体积(µL)", - "mix": "混匀", "name_your_transfer": "为您的快速移液流程命名", "none_to_show": "没有快速移液可显示!", "number_wells_selected_error_learn_more": "具有多个源孔{{selectionUnits}}的快速移液是可以进行一对一或者多对多移液的(为此移液流程同样选择{{wellCount}}个目标孔位{{selectionUnits}})或进行多对一移液,即合并为单个孔位(选择1个目标孔{{selectionUnit}})。", @@ -89,24 +91,24 @@ "pin_transfer": "快速移液", "pinned_transfer": "固定快速移液", "pinned_transfers": "固定快速移液", + "pipette": "移液器", + "pipette_currently_attached": "快速移液移液器选项取决于当前您工作站上安装的移液器.", + "pipette_path": "移液器路径", "pipette_path_multi_aspirate": "多次吸取", - "pipette_path_multi_dispense_volume_blowout": "多次分液,{{volume}} 微升废弃量,在{{blowOutLocation}}吹出", "pipette_path_multi_dispense": "多次分液", + "pipette_path_multi_dispense_volume_blowout": "多次分液,{{volume}} 微升废弃量,在{{blowOutLocation}}吹出", "pipette_path_single": "单次转移", - "pipette_path": "移液器路径", - "pipette_currently_attached": "快速移液移液器选项取决于当前您工作站上安装的移液器.", - "pipette": "移液器", "pre_wet_tip": "润湿吸头", - "quick_transfer_volume": "快速移液{{volume}}µL", "quick_transfer": "快速移液", - "right_mount": "右侧支架", + "quick_transfer_volume": "快速移液{{volume}}µL", "reservoir": "储液槽", + "right_mount": "右侧支架", "run_now": "立即运行", "run_quick_transfer_now": "您想立即运行快速移液流程吗?", "run_transfer": "运行快速移液", "save": "保存", - "save_to_run_later": "保存您的快速移液流程以备后续运行.", "save_for_later": "保存备用", + "save_to_run_later": "保存您的快速移液流程以备后续运行.", "select_attached_pipette": "选择已连接的移液器", "select_by": "按...选择", "select_dest_labware": "选择目标实验耗材", @@ -117,23 +119,23 @@ "set_aspirate_volume": "设置吸液体积", "set_dispense_volume": "设置排液体积", "set_transfer_volume": "设置移液体积", + "source": "源", "source_labware": "源实验耗材", "source_labware_c2": "C2 中的源实验耗材", - "source": "源", "starting_well": "起始孔", "storage_limit_reached": "已达到存储限制", - "use_deck_slots": "快速移液将使用板位B2-D2。这些板位将用于放置吸头盒、源实验耗材和目标实验耗材。请确保使用最新的甲板配置,避免碰撞。", "tip_drop_location": "吸头丢弃位置", "tip_management": "吸头管理", - "tip_position_value": "距底部 {{position}} mm", "tip_position": "移液器位置", + "tip_position_value": "距底部 {{position}} mm", "tip_rack": "吸头盒", "too_many_pins_body": "删除一个快速移液,以便向您的固定列表中添加更多传输。", "too_many_pins_header": "您已达到上限!", + "touch_tip": "碰壁动作", + "touch_tip_after_aspirating": "吸液后触碰吸头", "touch_tip_before_dispensing": "在分液前做碰壁动作", "touch_tip_position_mm": "在孔底部做碰壁动作的高度(mm)", "touch_tip_value": "距底部 {{position}} mm", - "touch_tip": "碰壁动作", "transfer_analysis_failed": "快速移液分析失败", "transfer_name": "移液名称", "trashBin": "垃圾桶", @@ -141,16 +143,17 @@ "tubeRack": "试管架", "unpin_transfer": "取消固定的快速移液", "unpinned_transfer": "已取消固定的快速移液", + "use_deck_slots": "快速移液将使用板位B2-D2。这些板位将用于放置吸头盒、源实验耗材和目标实验耗材。请确保使用最新的甲板配置,避免碰撞。", + "value_out_of_range": "值必须在{{min}}-{{max}}之间", "volume_per_well": "每孔体积", "volume_per_well_µL": "每孔体积(µL)", - "value_out_of_range": "值必须在{{min}}-{{max}}之间", "wasteChute": "外置垃圾槽", "wasteChute_location": "位于{{slotName}}的外置垃圾槽", "welcome_to_quick_transfer": "欢迎使用快速移液!", + "well": "孔", "wellPlate": "孔板", - "well_selection": "孔位选择", "well_ratio": "快速移液可以一对一或者多对多进行移液的(为此移液操作选择同样数量的{{wells}})或可以多对一,也就是合并为单孔(选择1个目标孔位)。", - "well": "孔", + "well_selection": "孔位选择", "wells": "孔", "will_be_deleted": "{{transferName}} 将被永久删除。" } diff --git a/app/src/assets/localization/zh/run_details.json b/app/src/assets/localization/zh/run_details.json index 2bfa9c1a5e1..b6fabcfe08c 100644 --- a/app/src/assets/localization/zh/run_details.json +++ b/app/src/assets/localization/zh/run_details.json @@ -1,10 +1,11 @@ { "analysis_failure_on_robot": "尝试在{{robotName}}上分析{{protocolName}}时发生错误。请修复以下错误,然后再次尝试运行此协议。", "analyzing_on_robot": "移液工作站分析中", - "anticipated_step": "预期步骤", "anticipated": "预期步骤", + "anticipated_step": "预期步骤", "apply_stored_data": "应用存储的数据", "apply_stored_labware_offset_data": "应用已储存的耗材校准数据?", + "cancel_run": "取消运行", "cancel_run_alert_info_flex": "该动作将终止本次运行并使移液器归位。", "cancel_run_alert_info_ot2": "该动作将终止本次运行,已拾取的吸头将被丢弃,移液器将归位。", "cancel_run_and_restart": "取消运行,重新进行设置以进行编辑", @@ -12,56 +13,56 @@ "cancel_run_modal_confirm": "是,取消运行", "cancel_run_modal_heading": "确定要取消吗?", "cancel_run_module_info": "此外,协议中使用的模块将保持激活状态,直到被禁用。", - "cancel_run": "取消运行", - "canceling_run_dot": "正在取消运行...", "canceling_run": "正在取消运行", - "clear_protocol_to_make_available": "清除工作站的协议以使其可用", + "canceling_run_dot": "正在取消运行...", "clear_protocol": "清除协议", - "close_door_to_resume_run": "关闭工作站门以继续运行", - "close_door_to_resume": "关闭移液工作站的前门以继续运行", + "clear_protocol_to_make_available": "清除工作站的协议以使其可用", "close_door": "关闭移液工作站前门", + "close_door_to_resume": "关闭移液工作站的前门以继续运行", + "close_door_to_resume_run": "关闭工作站门以继续运行", "closing_protocol": "正在关闭协议", - "comment_step": "注释", "comment": "注释", + "comment_step": "注释", "complete_protocol_to_download": "完成协议以下载运行日志", - "current_step_pause_timer": "计时器", - "current_step_pause": "当前步骤 - 用户暂停", "current_step": "当前步骤", + "current_step_pause": "当前步骤 - 用户暂停", + "current_step_pause_timer": "计时器", "current_temperature": "当前:{{temperature}}°C", "custom_values": "自定义值", "data_out_of_date": "此数据可能已过期", "date": "日期", + "device_details": "设备详细信息", "door_is_open": "工作站前门已打开", "door_open_pause": "当前步骤 - 暂停 - 前门已打开", - "download_files": "下载文件", "download": "下载", + "download_files": "下载文件", "download_run_log": "下载运行日志", "downloading_run_log": "正在下载运行日志", "drop_tip": "在{{labware_location}}内的{{labware}}中的{{well_name}}中丢弃吸头", "duration": "持续时间", + "end": "结束", "end_of_protocol": "协议结束", "end_step_time": "结束", - "end": "结束", "error_details": "错误详情", "error_info": "错误{{errorCode}}:{{errorType}}", "error_type": "错误:{{errorType}}", "failed_step": "步骤失败", + "files_available_robot_details": "与协议运行相关的所有文件均可在工作站详情页面查看。", "final_step": "最后一步", "ignore_stored_data": "忽略已存储的数据", - "labware_offset_data": "耗材校准数据", "labware": "耗材", + "labware_offset_data": "耗材校准数据", "left": "左", "listed_values": "列出的值仅供查看", - "load_liquids_info_protocol_setup": "将{{liquid}}加载到{{labware}}中", + "load_labware_info_protocol_setup_plural": "在{{module_name}}中加载{{labware}}", "load_module_protocol_setup_plural": "加载{{module}}", - "load_module_protocol_setup": "在{{slot_name}}号板位中加载{{module}}", - "load_pipette_protocol_setup": "在{{mount_name}}安装位上加载{{pipette_name}}", - "loading_protocol": "正在加载协议", "loading_data": "正在加载数据...", + "loading_protocol": "正在加载协议", "location": "位置", "module_controls": "模块控制", "module_slot_number": "板位{{slot_number}}", "move_labware": "移动耗材", + "na": "不适用", "name": "名称", "no_files_included": "未包含协议文件", "no_of_error": "{{count}}个错误", @@ -74,9 +75,9 @@ "not_started_yet": "未开始", "off_deck": "甲板外", "parameters": "参数", + "pause": "暂停", "pause_protocol": "暂停协议", "pause_run": "暂停运行", - "pause": "暂停", "paused_for": "暂停原因", "pickup_tip": "从{{labware_location}}内的{{labware}}中的{{well_name}}孔位拾取吸头", "plus_more": "+{{count}}更多", @@ -100,39 +101,39 @@ "right": "右", "robot_has_previous_offsets": "该移液工作站已存储了之前运行协议的耗材校准数据。您想将这些数据应用于此协议的运行吗?您仍然可以通过实验器具位置检查调整校准数据。", "robot_was_recalibrated": "在储存此耗材校准数据后,移液工作站已重新校准", + "run": "运行", "run_again": "再次运行", + "run_canceled": "运行已取消。", "run_canceled_splash": "运行已取消", - "run_canceled_with_errors_splash": "因错误取消运行。", "run_canceled_with_errors": "因错误取消运行。", - "run_canceled": "运行已取消。", + "run_canceled_with_errors_splash": "因错误取消运行。", + "run_complete": "运行已完成", + "run_completed": "运行已完成。", "run_completed_splash": "运行完成", - "run_completed_with_warnings_splash": "运行完成,并伴有警告。", "run_completed_with_warnings": "运行完成,并伴有警告。", - "run_completed": "运行已完成。", - "run_complete_splash": "运行已完成", - "run_complete": "运行已完成", + "run_completed_with_warnings_splash": "运行完成,并伴有警告。", "run_cta_disabled": "在开始运行之前,请完成协议选项卡上的所有必要步骤。", + "run_failed": "运行失败。", "run_failed_modal_body": "在协议执行{{command}}时发生错误。", "run_failed_modal_header": "{{errorName}}:{{errorCode}}协议步骤{{count}}", "run_failed_modal_title": "运行失败", "run_failed_splash": "运行失败", - "run_failed": "运行失败。", "run_has_diverged_from_predicted": "运行已偏离预期状态。无法执行新的预期步骤。", "run_preview": "运行预览", "run_protocol": "运行协议", "run_status": "状态:{{status}}", "run_time": "运行时间", - "run": "运行", - "setup_incomplete": "完成“设置”选项卡中所需的步骤", "setup": "设置", + "setup_incomplete": "完成“设置”选项卡中所需的步骤", "slot": "板位{{slotName}}", + "start": "开始", "start_run": "开始运行", "start_step_time": "开始", "start_time": "开始时间", - "start": "开始", + "status": "状态", + "status_awaiting-recovery": "等待恢复", "status_awaiting-recovery-blocked-by-open-door": "暂停 - 门已打开", "status_awaiting-recovery-paused": "暂停", - "status_awaiting-recovery": "等待恢复", "status_blocked-by-open-door": "暂停 - 前门打开", "status_failed": "失败", "status_finishing": "结束中", @@ -142,9 +143,9 @@ "status_stop-requested": "请求停止", "status_stopped": "已取消", "status_succeeded": "已完成", - "status": "状态", "step": "步骤", "step_failed": "步骤失败", + "step_na": "步骤:不适用", "step_number": "步骤{{step_number}}:", "steps_total": "总计{{count}}步", "stored_labware_offset_data": "已储存适用于此协议的耗材校准数据", @@ -152,13 +153,13 @@ "temperature_not_available": "{{temperature_type}}: n/a", "thermocycler_error_tooltip": "模块遇到异常,请联系技术支持。", "total_elapsed_time": "总耗时", - "total_step_count_plural": "总计{{count}}步", "total_step_count": "总计{{count}}步", + "total_step_count_plural": "总计{{count}}步", "unable_to_determine_steps": "无法确定步骤", "view_analysis_error_details": "查看 错误详情", "view_current_step": "查看当前步骤", - "view_error_details": "查看错误详情", "view_error": "查看错误", + "view_error_details": "查看错误详情", "view_warning_details": "查看警告详情", "warning_details": "警告详情" } diff --git a/app/src/assets/localization/zh/shared.json b/app/src/assets/localization/zh/shared.json index 90b597b2820..694e7b80037 100644 --- a/app/src/assets/localization/zh/shared.json +++ b/app/src/assets/localization/zh/shared.json @@ -10,15 +10,16 @@ "change_protocol": "更改协议", "change_robot": "更换工作站", "clear_data": "清除数据", - "close_robot_door": "开始运行前请关闭工作站前门。", "close": "关闭", + "close_robot_door": "开始运行前请关闭工作站前门。", + "closed": "已关闭", + "confirm": "确认", "confirm_placement": "确认放置", "confirm_position": "确认位置", "confirm_values": "确认这些值", - "confirm": "确认", + "continue": "继续", "continue_activity": "继续活动", "continue_to_param": "继续设置参数", - "continue": "继续", "delete": "删除", "did_pipette_pick_up_tip": "移液器是否成功拾取吸头?", "disabled_cannot_connect": "无法连接到工作站", @@ -29,8 +30,8 @@ "drag_and_drop": "拖放或 浏览 您的文件", "empty": "空闲", "ending": "结束中", - "error_encountered": "遇到错误", "error": "错误", + "error_encountered": "遇到错误", "exit": "退出", "extension_mount": "扩展安装支架", "flow_complete": "{{flowName}}完成!", @@ -40,8 +41,8 @@ "instruments": "硬件", "loading": "加载中...", "next": "下一步", - "no_data": "无数据", "no": "否", + "no_data": "无数据", "none": "无", "not_used": "未使用", "off": "关闭", @@ -51,18 +52,18 @@ "proceed_to_setup": "继续设置", "protocol_run_general_error_msg": "无法在工作站上创建协议运行。", "reanalyze": "重新分析", - "refresh_list": "刷新列表", "refresh": "刷新", + "refresh_list": "刷新列表", "remember_my_selection_and_do_not_ask_again": "记住我的选择,不再询问", - "reset_all": "全部重置", "reset": "重置", + "reset_all": "全部重置", "restart": "重新启动", "resume": "继续", "return": "返回", "reverse": "按字母倒序排序", "robot_is_analyzing": "工作站正在分析", - "robot_is_busy_no_protocol_run_allowed": "此工作站正忙,无法运行此协议。转到工作站", "robot_is_busy": "工作站正忙", + "robot_is_busy_no_protocol_run_allowed": "此工作站正忙,无法运行此协议。转到工作站", "robot_is_reachable_but_not_responding": "此工作站的API服务器未能正确响应IP地址{{hostname}}处的请求", "robot_was_seen_but_is_unreachable": "最近看到此工作站,但当前无法访问IP地址{{hostname}}", "save": "保存", @@ -73,11 +74,11 @@ "starting": "启动中", "step": "步骤{{current}}/{{max}}", "stop": "停止", - "terminate_activity": "终止活动", "terminate": "终止远程活动", + "terminate_activity": "终止活动", "try_again": "重试", - "unknown_error": "发生未知错误", "unknown": "未知", + "unknown_error": "发生未知错误", "update": "更新", "view_latest_release_notes": "查看最新发布说明:", "yes": "是", diff --git a/app/src/assets/localization/zh/top_navigation.json b/app/src/assets/localization/zh/top_navigation.json index cb831731be9..79de9180bb8 100644 --- a/app/src/assets/localization/zh/top_navigation.json +++ b/app/src/assets/localization/zh/top_navigation.json @@ -1,20 +1,25 @@ { - "all_protocols": "全部协议", + "app_settings": "APP设置", "attached_pipettes_do_not_match": "安装的移液器与加载的协议中指定的移液器不匹配", "calibrate_deck_to_proceed": "校准甲板以继续", + "calibration_dashboard": "校准面板", "deck_setup": "甲板设置", + "device": "设备", "devices": "设备", "instruments": "硬件", "labware": "耗材", "modules": "模块", - "pipettes_not_calibrated": "请校准加载的协议中指定的所有移液器以继续", "pipettes": "移液器", + "pipettes_not_calibrated": "请校准加载的协议中指定的所有移液器以继续", "please_connect_to_a_robot": "请连接到工作站以继续", "please_load_a_protocol": "请加载协议以继续", + "protocol_details": "协议详细信息", "protocol_runs": "协议运行", + "protocol_timeline": "协议时间线", "protocols": "协议", "quick_transfer": "快速移液", "robot_settings": "工作站设置", "run": "运行", + "run_details": "运行详细信息", "settings": "设置" } diff --git a/app/src/local-resources/commands/utils/lastRunCommandPromptedErrorRecovery.ts b/app/src/local-resources/commands/utils/lastRunCommandPromptedErrorRecovery.ts index dd07756ef43..673ed431220 100644 --- a/app/src/local-resources/commands/utils/lastRunCommandPromptedErrorRecovery.ts +++ b/app/src/local-resources/commands/utils/lastRunCommandPromptedErrorRecovery.ts @@ -1,13 +1,12 @@ import type { RunCommandSummary } from '@opentrons/api-client' - -// Whether the last run protocol command prompted Error Recovery. +// Whether the last run protocol command prompted Error Recovery, if Error Recovery is enabled. export function lastRunCommandPromptedErrorRecovery( - summary: RunCommandSummary[] + summary: RunCommandSummary[] | null, + isEREnabled: boolean ): boolean { - const lastProtocolCommand = summary.findLast( + const lastProtocolCommand = summary?.findLast( command => command.intent !== 'fixit' && command.error != null ) - // All recoverable protocol commands have defined errors. - return lastProtocolCommand?.error?.isDefined ?? false + return isEREnabled ? lastProtocolCommand?.error?.isDefined ?? false : false } diff --git a/app/src/local-resources/labware/hooks/useAllLabware.ts b/app/src/local-resources/labware/hooks/useAllLabware.ts index 28d4325b2eb..b118113ad55 100644 --- a/app/src/local-resources/labware/hooks/useAllLabware.ts +++ b/app/src/local-resources/labware/hooks/useAllLabware.ts @@ -3,12 +3,21 @@ import { getValidCustomLabware } from '/app/redux/custom-labware' import { getAllDefinitions } from '../utils' import type { LabwareSort, LabwareFilter, LabwareDefAndDate } from '../types' +// labware to filter out from the labware tab of the desktop app +// TODO (sb:1/14/25) remove evotips from blocklist before public launch +const LABWARE_LOADNAME_BLOCKLIST = [ + 'evotips_flex_96_tiprack_adapter', + 'evotips_opentrons_96_labware', +] + export function useAllLabware( sortBy: LabwareSort, filterBy: LabwareFilter ): LabwareDefAndDate[] { const fullLabwareList: LabwareDefAndDate[] = [] - const labwareDefinitions = getAllDefinitions() + const labwareDefinitions = getAllDefinitions().filter( + def => !LABWARE_LOADNAME_BLOCKLIST.includes(def.parameters.loadName) + ) labwareDefinitions.forEach(def => fullLabwareList.push({ definition: def })) const customLabwareList = useSelector(getValidCustomLabware) customLabwareList.forEach(customLabware => diff --git a/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderBannerContainer/TerminalRunBannerContainer.tsx b/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderBannerContainer/TerminalRunBannerContainer.tsx index c6428c2f385..4148a791611 100644 --- a/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderBannerContainer/TerminalRunBannerContainer.tsx +++ b/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderBannerContainer/TerminalRunBannerContainer.tsx @@ -40,12 +40,15 @@ export function useTerminalRunBannerContainer({ const completedWithErrors = (commandErrorList != null && commandErrorList.length > 0) || highestPriorityError != null + // TODO(jh, 01-10-25): Adding /commandErrors to notifications accomplishes the below with reduced latency. + const completedWithNoErrors = + commandErrorList != null && commandErrorList.length === 0 const showSuccessBanner = runStatus === RUN_STATUS_SUCCEEDED && isRunCurrent && !isResetRunLoading && - !completedWithErrors + completedWithNoErrors // TODO(jh, 08-14-24): Ideally, the backend never returns the "user cancelled a run" error and // cancelledWithoutRecovery becomes unnecessary. @@ -118,14 +121,10 @@ function ProtocolRunErrorBanner({ const { closeCurrentRun } = useCloseCurrentRun() - const { highestPriorityError, commandErrorList } = runErrors + const { highestPriorityError } = runErrors const handleFailedRunClick = (): void => { - // TODO(jh, 08-15-24): Revisit the control flow here here after - // commandErrorList may be fetched for a non-current run. - if (commandErrorList == null) { - closeCurrentRun() - } + closeCurrentRun() runHeaderModalContainerUtils.runFailedModalUtils.toggleModal() } diff --git a/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderModalContainer/RunHeaderModalContainer.tsx b/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderModalContainer/RunHeaderModalContainer.tsx index 0c306339f69..8486296122b 100644 --- a/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderModalContainer/RunHeaderModalContainer.tsx +++ b/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderModalContainer/RunHeaderModalContainer.tsx @@ -52,6 +52,7 @@ export function RunHeaderModalContainer( runStatus={runStatus} runId={runId} unvalidatedFailedCommand={recoveryModalUtils.failedCommand} + runLwDefsByUri={recoveryModalUtils.runLwDefsByUri} protocolAnalysis={robotProtocolAnalysis} /> ) : null} diff --git a/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderModalContainer/hooks/useRunHeaderDropTip.ts b/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderModalContainer/hooks/useRunHeaderDropTip.ts index 82d9c30c84b..3363a225ec7 100644 --- a/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderModalContainer/hooks/useRunHeaderDropTip.ts +++ b/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderModalContainer/hooks/useRunHeaderDropTip.ts @@ -2,6 +2,7 @@ import { useEffect } from 'react' import { RUN_STATUS_IDLE, RUN_STATUS_STOPPED } from '@opentrons/api-client' import { FLEX_ROBOT_TYPE, OT2_ROBOT_TYPE } from '@opentrons/shared-data' +import { useErrorRecoverySettings } from '@opentrons/react-api-client' import { useDropTipWizardFlows } from '/app/organisms/DropTipWizardFlows' import { useProtocolDropTipModal } from '../modals' @@ -11,8 +12,8 @@ import { useIsRunCurrent, } from '/app/resources/runs' import { isTerminalRunStatus } from '../../utils' -import { lastRunCommandPromptedErrorRecovery } from '/app/local-resources/commands' import { useTipAttachmentStatus } from '/app/resources/instruments' +import { lastRunCommandPromptedErrorRecovery } from '/app/local-resources/commands' import type { RobotType } from '@opentrons/shared-data' import type { Run, RunStatus } from '@opentrons/api-client' @@ -104,6 +105,8 @@ export function useRunHeaderDropTip({ : { showDTWiz: false, dtWizProps: null } } + const { data } = useErrorRecoverySettings() + const isEREnabled = data?.data.enabled ?? true const runSummaryNoFixit = useCurrentRunCommands( { includeFixitCommands: false, @@ -111,6 +114,7 @@ export function useRunHeaderDropTip({ }, { enabled: isTerminalRunStatus(runStatus) } ) + // Manage tip checking useEffect(() => { // If a user begins a new run without navigating away from the run page, reset tip status. @@ -118,21 +122,16 @@ export function useRunHeaderDropTip({ if (runStatus === RUN_STATUS_IDLE) { resetTipStatus() } - // Only determine tip status when necessary as this can be an expensive operation. Error Recovery handles tips, so don't - // have to do it here if done during Error Recovery. + // Only run tip checking if it wasn't *just* handled during Error Recovery. else if ( - runSummaryNoFixit != null && - runSummaryNoFixit.length > 0 && - !lastRunCommandPromptedErrorRecovery(runSummaryNoFixit) && + !lastRunCommandPromptedErrorRecovery(runSummaryNoFixit, isEREnabled) && + isRunCurrent && isTerminalRunStatus(runStatus) ) { void determineTipStatus() } } - }, [runStatus, robotType, runSummaryNoFixit]) - - // TODO(jh, 08-15-24): The enteredER condition is a hack, because errorCommands are only returned when a run is current. - // Ideally the run should not need to be current to view errorCommands. + }, [runStatus, robotType, isRunCurrent, runSummaryNoFixit, isEREnabled]) // If the run terminates with a "stopped" status, close the run if no tips are attached after running tip check at least once. // This marks the robot as "not busy" if drop tip CTAs are unnecessary. @@ -140,8 +139,7 @@ export function useRunHeaderDropTip({ if ( runStatus === RUN_STATUS_STOPPED && isRunCurrent && - (initialPipettesWithTipsCount === 0 || robotType === OT2_ROBOT_TYPE) && - !enteredER + (initialPipettesWithTipsCount === 0 || robotType === OT2_ROBOT_TYPE) ) { closeCurrentRun() } diff --git a/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/hooks/useRunErrors.ts b/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/hooks/useRunErrors.ts index 4d66b367a0e..593c435029b 100644 --- a/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/hooks/useRunErrors.ts +++ b/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/hooks/useRunErrors.ts @@ -1,7 +1,6 @@ import { useRunCommandErrors } from '@opentrons/react-api-client' import { isTerminalRunStatus } from '../utils' -import { useMostRecentRunId } from '/app/resources/runs' import { getHighestPriorityError } from '/app/transformations/runs' import type { RunStatus, Run } from '@opentrons/api-client' @@ -27,14 +26,11 @@ export function useRunErrors({ runRecord, runStatus, }: UseRunErrorsProps): UseRunErrorsResult { - const mostRecentRunId = useMostRecentRunId() - const isMostRecentRun = mostRecentRunId === runId - const { data: commandErrorList } = useRunCommandErrors( runId, { cursor: 0, pageLength: ALL_COMMANDS_PAGE_LENGTH }, { - enabled: isTerminalRunStatus(runStatus) && isMostRecentRun, + enabled: isTerminalRunStatus(runStatus), } ) diff --git a/app/src/organisms/ErrorRecoveryFlows/__fixtures__/index.ts b/app/src/organisms/ErrorRecoveryFlows/__fixtures__/index.ts index 1a815b99c1e..aaf0b89e062 100644 --- a/app/src/organisms/ErrorRecoveryFlows/__fixtures__/index.ts +++ b/app/src/organisms/ErrorRecoveryFlows/__fixtures__/index.ts @@ -58,6 +58,7 @@ export const mockRecoveryContentProps: RecoveryContentProps = { byRunRecord: mockFailedCommand, byAnalysis: mockFailedCommand, }, + runLwDefsByUri: {} as any, errorKind: 'GENERAL_ERROR', robotType: FLEX_ROBOT_TYPE, runId: 'MOCK_RUN_ID', diff --git a/app/src/organisms/ErrorRecoveryFlows/__tests__/ErrorRecoveryFlows.test.tsx b/app/src/organisms/ErrorRecoveryFlows/__tests__/ErrorRecoveryFlows.test.tsx index 53bc8c15a8b..47f1668af87 100644 --- a/app/src/organisms/ErrorRecoveryFlows/__tests__/ErrorRecoveryFlows.test.tsx +++ b/app/src/organisms/ErrorRecoveryFlows/__tests__/ErrorRecoveryFlows.test.tsx @@ -45,6 +45,7 @@ vi.mock('react-redux', async () => { describe('useErrorRecoveryFlows', () => { beforeEach(() => { vi.mocked(useCurrentlyRecoveringFrom).mockReturnValue('mockCommand' as any) + vi.mocked(useRunLoadedLabwareDefinitionsByUri).mockReturnValue({}) }) it('should have initial state of isERActive as false', () => { @@ -89,12 +90,32 @@ describe('useErrorRecoveryFlows', () => { expect(result.current.failedCommand).toEqual('mockCommand') }) + it("should return the run's labware definitions", () => { + const { result } = renderHook(() => + useErrorRecoveryFlows('MOCK_ID', RUN_STATUS_RUNNING) + ) + + expect(result.current.failedCommand).toEqual('mockCommand') + }) + it(`should return isERActive false if the run status is ${RUN_STATUS_STOP_REQUESTED} before seeing ${RUN_STATUS_AWAITING_RECOVERY}`, () => { const { result } = renderHook(() => useErrorRecoveryFlows('MOCK_ID', RUN_STATUS_STOP_REQUESTED) ) - expect(result.current.isERActive).toEqual(false) + expect(result.current.runLwDefsByUri).toEqual({}) + }) + + it('should not return isERActive if the run labware defintions is null', () => { + vi.mocked(useRunLoadedLabwareDefinitionsByUri).mockReturnValue(null) + + const { result } = renderHook( + runStatus => useErrorRecoveryFlows('MOCK_ID', runStatus), + { + initialProps: RUN_STATUS_AWAITING_RECOVERY, + } + ) + expect(result.current.isERActive).toBe(false) }) it('should set hasSeenAwaitingRecovery to true when runStatus is RUN_STATUS_AWAITING_RECOVERY', () => { @@ -143,6 +164,7 @@ describe('ErrorRecoveryFlows', () => { unvalidatedFailedCommand: mockFailedCommand, runId: 'MOCK_RUN_ID', protocolAnalysis: null, + runLwDefsByUri: {}, } vi.mocked(ErrorRecoveryWizard).mockReturnValue(
MOCK WIZARD
) vi.mocked(RecoverySplash).mockReturnValue(
MOCK RUN PAUSED SPLASH
) @@ -167,7 +189,6 @@ describe('ErrorRecoveryFlows', () => { intent: 'recovering', showTakeover: false, }) - vi.mocked(useRunLoadedLabwareDefinitionsByUri).mockReturnValue({}) }) it('renders the wizard when showERWizard is true', () => { diff --git a/app/src/organisms/ErrorRecoveryFlows/hooks/__tests__/useDeckMapUtils.test.ts b/app/src/organisms/ErrorRecoveryFlows/hooks/__tests__/useDeckMapUtils.test.ts index 319ed573eb3..ff9ff758efc 100644 --- a/app/src/organisms/ErrorRecoveryFlows/hooks/__tests__/useDeckMapUtils.test.ts +++ b/app/src/organisms/ErrorRecoveryFlows/hooks/__tests__/useDeckMapUtils.test.ts @@ -197,17 +197,7 @@ describe('getRunCurrentModulesInfo', () => { const result = getRunCurrentModulesInfo({ runRecord: null as any, deckDef: mockDeckDef, - labwareDefinitionsByUri: {}, - }) - - expect(result).toEqual([]) - }) - - it('should return an empty array if protocolAnalysis is null', () => { - const result = getRunCurrentModulesInfo({ - runRecord: mockRunRecord, - deckDef: mockDeckDef, - labwareDefinitionsByUri: null, + runLwDefsByUri: {}, }) expect(result).toEqual([]) @@ -218,7 +208,7 @@ describe('getRunCurrentModulesInfo', () => { const result = getRunCurrentModulesInfo({ runRecord: mockRunRecord, deckDef: mockDeckDef, - labwareDefinitionsByUri: { + runLwDefsByUri: { 'opentrons/opentrons_96_pcr_adapter/1': 'MOCK_LW_DEF', } as any, }) @@ -241,7 +231,7 @@ describe('getRunCurrentModulesInfo', () => { data: { modules: [mockModule], labware: [] }, }, deckDef: mockDeckDef, - labwareDefinitionsByUri: {}, + runLwDefsByUri: {}, }) expect(result).toEqual([ { @@ -260,7 +250,7 @@ describe('getRunCurrentModulesInfo', () => { const result = getRunCurrentModulesInfo({ runRecord: mockRunRecord, deckDef: mockDeckDef, - labwareDefinitionsByUri: null, + runLwDefsByUri: {}, }) expect(result).toEqual([]) }) @@ -285,7 +275,7 @@ describe('getRunCurrentLabwareInfo', () => { it('should return an empty array if runRecord is null', () => { const result = getRunCurrentLabwareInfo({ runRecord: undefined, - labwareDefinitionsByUri: {} as any, + runLwDefsByUri: {} as any, }) expect(result).toEqual([]) @@ -294,7 +284,7 @@ describe('getRunCurrentLabwareInfo', () => { it('should return an empty array if protocolAnalysis is null', () => { const result = getRunCurrentLabwareInfo({ runRecord: { data: { labware: [] } } as any, - labwareDefinitionsByUri: null, + runLwDefsByUri: {}, }) expect(result).toEqual([]) @@ -308,7 +298,7 @@ describe('getRunCurrentLabwareInfo', () => { const result = getRunCurrentLabwareInfo({ runRecord: { data: { labware: [mockPickUpTipLwSlotName] } } as any, - labwareDefinitionsByUri: { + runLwDefsByUri: { [mockPickUpTipLabware.definitionUri]: mockLabwareDef, }, }) diff --git a/app/src/organisms/ErrorRecoveryFlows/hooks/useDeckMapUtils.ts b/app/src/organisms/ErrorRecoveryFlows/hooks/useDeckMapUtils.ts index 1c61644e482..435660c84a1 100644 --- a/app/src/organisms/ErrorRecoveryFlows/hooks/useDeckMapUtils.ts +++ b/app/src/organisms/ErrorRecoveryFlows/hooks/useDeckMapUtils.ts @@ -41,7 +41,7 @@ interface UseDeckMapUtilsProps { runId: ErrorRecoveryFlowsProps['runId'] protocolAnalysis: ErrorRecoveryFlowsProps['protocolAnalysis'] failedLabwareUtils: UseFailedLabwareUtilsResult - labwareDefinitionsByUri: ERUtilsProps['labwareDefinitionsByUri'] + runLwDefsByUri: ERUtilsProps['runLwDefsByUri'] runRecord: Run | undefined } @@ -64,7 +64,7 @@ export function useDeckMapUtils({ runRecord, runId, failedLabwareUtils, - labwareDefinitionsByUri, + runLwDefsByUri, }: UseDeckMapUtilsProps): UseDeckMapUtilsResult { const robotType = protocolAnalysis?.robotType ?? OT2_ROBOT_TYPE const deckConfig = getSimplestDeckConfigForProtocol(protocolAnalysis) @@ -77,9 +77,9 @@ export function useDeckMapUtils({ getRunCurrentModulesInfo({ runRecord, deckDef, - labwareDefinitionsByUri, + runLwDefsByUri, }), - [runRecord, deckDef, labwareDefinitionsByUri] + [runRecord, deckDef, runLwDefsByUri] ) const runCurrentModules = useMemo( @@ -93,8 +93,8 @@ export function useDeckMapUtils({ ) const currentLabwareInfo = useMemo( - () => getRunCurrentLabwareInfo({ runRecord, labwareDefinitionsByUri }), - [runRecord, labwareDefinitionsByUri] + () => getRunCurrentLabwareInfo({ runRecord, runLwDefsByUri }), + [runRecord, runLwDefsByUri] ) const { updatedModules, remainingLabware } = useMemo( @@ -113,32 +113,24 @@ export function useDeckMapUtils({ ) const movedLabwareDef = - labwareDefinitionsByUri != null && failedLabwareUtils.failedLabware != null - ? labwareDefinitionsByUri[failedLabwareUtils.failedLabware.definitionUri] + runLwDefsByUri != null && failedLabwareUtils.failedLabware != null + ? runLwDefsByUri[failedLabwareUtils.failedLabware.definitionUri] : null const moduleRenderInfo = useMemo( () => - runRecord != null && labwareDefinitionsByUri != null - ? getRunModuleRenderInfo( - runRecord.data, - deckDef, - labwareDefinitionsByUri - ) + runRecord != null && runLwDefsByUri != null + ? getRunModuleRenderInfo(runRecord.data, deckDef, runLwDefsByUri) : [], - [deckDef, labwareDefinitionsByUri, runRecord] + [deckDef, runLwDefsByUri, runRecord] ) const labwareRenderInfo = useMemo( () => - runRecord != null && labwareDefinitionsByUri != null - ? getRunLabwareRenderInfo( - runRecord.data, - labwareDefinitionsByUri, - deckDef - ) + runRecord != null && runLwDefsByUri != null + ? getRunLabwareRenderInfo(runRecord.data, runLwDefsByUri, deckDef) : [], - [deckDef, labwareDefinitionsByUri, runRecord] + [deckDef, runLwDefsByUri, runRecord] ) return { @@ -257,13 +249,13 @@ interface RunCurrentModuleInfo { export const getRunCurrentModulesInfo = ({ runRecord, deckDef, - labwareDefinitionsByUri, + runLwDefsByUri, }: { runRecord: UseDeckMapUtilsProps['runRecord'] deckDef: DeckDefinition - labwareDefinitionsByUri?: LabwareDefinitionsByUri | null + runLwDefsByUri: UseDeckMapUtilsProps['runLwDefsByUri'] }): RunCurrentModuleInfo[] => { - if (runRecord == null || labwareDefinitionsByUri == null) { + if (runRecord == null) { return [] } else { return runRecord.data.modules.reduce( @@ -280,7 +272,7 @@ export const getRunCurrentModulesInfo = ({ const nestedLabwareDef = nestedLabware != null - ? labwareDefinitionsByUri[nestedLabware.definitionUri] + ? runLwDefsByUri[nestedLabware.definitionUri] : null const slotPosition = getPositionFromSlotId( @@ -324,12 +316,12 @@ interface RunCurrentLabwareInfo { // Derive the labware info necessary to render labware on the deck. export function getRunCurrentLabwareInfo({ runRecord, - labwareDefinitionsByUri, + runLwDefsByUri, }: { runRecord: UseDeckMapUtilsProps['runRecord'] - labwareDefinitionsByUri?: LabwareDefinitionsByUri | null + runLwDefsByUri: UseDeckMapUtilsProps['runLwDefsByUri'] }): RunCurrentLabwareInfo[] { - if (runRecord == null || labwareDefinitionsByUri == null) { + if (runRecord == null) { return [] } else { const allLabware = runRecord.data.labware.reduce( @@ -340,7 +332,7 @@ export function getRunCurrentLabwareInfo({ runRecord, true ) // Exclude modules since handled separately. - const labwareDef = getLabwareDefinition(lw, labwareDefinitionsByUri) + const labwareDef = getLabwareDefinition(lw, runLwDefsByUri) if (slotName == null || labwareLocation == null) { return acc diff --git a/app/src/organisms/ErrorRecoveryFlows/hooks/useERUtils.ts b/app/src/organisms/ErrorRecoveryFlows/hooks/useERUtils.ts index 72e9bb481bc..4bd4a93643f 100644 --- a/app/src/organisms/ErrorRecoveryFlows/hooks/useERUtils.ts +++ b/app/src/organisms/ErrorRecoveryFlows/hooks/useERUtils.ts @@ -22,11 +22,7 @@ import { useCleanupRecoveryState } from './useCleanupRecoveryState' import { useFailedPipetteUtils } from './useFailedPipetteUtils' import { getRunningStepCountsFrom } from '/app/resources/protocols' -import type { - LabwareDefinition2, - LabwareDefinitionsByUri, - RobotType, -} from '@opentrons/shared-data' +import type { LabwareDefinition2, RobotType } from '@opentrons/shared-data' import type { IRecoveryMap, RouteStep, RecoveryRoute } from '../types' import type { ErrorRecoveryFlowsProps } from '..' import type { UseRouteUpdateActionsResult } from './useRouteUpdateActions' @@ -54,7 +50,6 @@ export type ERUtilsProps = Omit & { failedCommand: ReturnType isActiveUser: UseRecoveryTakeoverResult['isActiveUser'] allRunDefs: LabwareDefinition2[] - labwareDefinitionsByUri: LabwareDefinitionsByUri | null } export interface ERUtilsResults { @@ -90,7 +85,7 @@ export function useERUtils({ isActiveUser, allRunDefs, unvalidatedFailedCommand, - labwareDefinitionsByUri, + runLwDefsByUri, }: ERUtilsProps): ERUtilsResults { const { data: attachedInstruments } = useInstrumentsQuery() const { data: runRecord } = useNotifyRunQuery(runId) @@ -185,7 +180,7 @@ export function useERUtils({ runRecord, protocolAnalysis, failedLabwareUtils, - labwareDefinitionsByUri, + runLwDefsByUri, }) const recoveryActionMutationUtils = useRecoveryActionMutation( diff --git a/app/src/organisms/ErrorRecoveryFlows/index.tsx b/app/src/organisms/ErrorRecoveryFlows/index.tsx index 84938e2db77..24834c86305 100644 --- a/app/src/organisms/ErrorRecoveryFlows/index.tsx +++ b/app/src/organisms/ErrorRecoveryFlows/index.tsx @@ -28,11 +28,12 @@ import { useRecoveryTakeover, useRetainedFailedCommandBySource, } from './hooks' +import { useRunLoadedLabwareDefinitionsByUri } from '/app/resources/runs' import type { RunStatus } from '@opentrons/api-client' import type { CompletedProtocolAnalysis } from '@opentrons/shared-data' import type { FailedCommand } from './types' -import { useRunLoadedLabwareDefinitionsByUri } from '/app/resources/runs' +import type { RunLoadedLabwareDefinitionsByUri } from '/app/resources/runs' const VALID_ER_RUN_STATUSES: RunStatus[] = [ RUN_STATUS_AWAITING_RECOVERY, @@ -53,10 +54,24 @@ const INVALID_ER_RUN_STATUSES: RunStatus[] = [ RUN_STATUS_IDLE, ] -export interface UseErrorRecoveryResult { +interface UseErrorRecoveryResultBase { isERActive: boolean failedCommand: FailedCommand | null + runLwDefsByUri: ReturnType +} +export interface UseErrorRecoveryActiveResult + extends UseErrorRecoveryResultBase { + isERActive: true + failedCommand: FailedCommand + runLwDefsByUri: RunLoadedLabwareDefinitionsByUri +} +export interface UseErrorRecoveryInactiveResult + extends UseErrorRecoveryResultBase { + isERActive: false } +export type UseErrorRecoveryResult = + | UseErrorRecoveryInactiveResult + | UseErrorRecoveryActiveResult export function useErrorRecoveryFlows( runId: string, @@ -64,6 +79,7 @@ export function useErrorRecoveryFlows( ): UseErrorRecoveryResult { const [isERActive, setIsERActive] = useState(false) const failedCommand = useCurrentlyRecoveringFrom(runId, runStatus) + const runLwDefsByUri = useRunLoadedLabwareDefinitionsByUri(runId) // The complexity of this logic exists to persist Error Recovery screens past the server's definition of Error Recovery. // Ex, show a "cancelling run" modal in Error Recovery flows despite the robot no longer being in a recoverable state. @@ -85,8 +101,7 @@ export function useErrorRecoveryFlows( if (runStatus != null) { const isAwaitingRecovery = VALID_ER_RUN_STATUSES.includes(runStatus) && - runStatus !== RUN_STATUS_STOP_REQUESTED && - failedCommand != null // Prevents one render cycle of an unknown failed command. + runStatus !== RUN_STATUS_STOP_REQUESTED if (isAwaitingRecovery) { setIsERActive(isValidERStatus(runStatus, true)) @@ -96,10 +111,14 @@ export function useErrorRecoveryFlows( } }, [runStatus, failedCommand]) - return { - isERActive, - failedCommand, - } + // Gate ER rendering on data derived from key network requests. + return isERActive && failedCommand != null && runLwDefsByUri != null + ? { + isERActive: true, + failedCommand, + runLwDefsByUri, + } + : { isERActive: false, failedCommand, runLwDefsByUri } } export interface ErrorRecoveryFlowsProps { @@ -109,14 +128,20 @@ export interface ErrorRecoveryFlowsProps { * information derived from the failed command from the run record even if there is no matching command in protocol analysis. * Using a failed command that is not matched to a protocol analysis command is unsafe in most circumstances (ie, in * non-generic recovery flows. Prefer using failedCommandBySource in most circumstances. */ - unvalidatedFailedCommand: FailedCommand | null + unvalidatedFailedCommand: UseErrorRecoveryActiveResult['failedCommand'] + runLwDefsByUri: UseErrorRecoveryActiveResult['runLwDefsByUri'] protocolAnalysis: CompletedProtocolAnalysis | null } export function ErrorRecoveryFlows( props: ErrorRecoveryFlowsProps ): JSX.Element | null { - const { protocolAnalysis, runStatus, unvalidatedFailedCommand, runId } = props + const { + protocolAnalysis, + runStatus, + unvalidatedFailedCommand, + runLwDefsByUri, + } = props const failedCommandBySource = useRetainedFailedCommandBySource( unvalidatedFailedCommand, @@ -128,11 +153,7 @@ export function ErrorRecoveryFlows( const robotType = protocolAnalysis?.robotType ?? OT2_ROBOT_TYPE const robotName = useHost()?.robotName ?? 'robot' - const labwareDefinitionsByUri = useRunLoadedLabwareDefinitionsByUri(runId) - const allRunDefs = - labwareDefinitionsByUri != null - ? Object.values(labwareDefinitionsByUri) - : [] + const allRunDefs = runLwDefsByUri != null ? Object.values(runLwDefsByUri) : [] const { showTakeover, @@ -150,7 +171,7 @@ export function ErrorRecoveryFlows( isActiveUser, failedCommand: failedCommandBySource, allRunDefs, - labwareDefinitionsByUri, + runLwDefsByUri, }) const renderWizard = diff --git a/app/src/organisms/ErrorRecoveryFlows/shared/GripperIsHoldingLabware.tsx b/app/src/organisms/ErrorRecoveryFlows/shared/GripperIsHoldingLabware.tsx index 036f1aff3d0..d198dcc8dac 100644 --- a/app/src/organisms/ErrorRecoveryFlows/shared/GripperIsHoldingLabware.tsx +++ b/app/src/organisms/ErrorRecoveryFlows/shared/GripperIsHoldingLabware.tsx @@ -29,12 +29,15 @@ export const HOLDING_LABWARE_OPTIONS: HoldingLabwareOption[] = [ export function GripperIsHoldingLabware({ routeUpdateActions, currentRecoveryOptionUtils, + recoveryCommands, }: RecoveryContentProps): JSX.Element { const { proceedNextStep, proceedToRouteAndStep, goBackPrevStep, + handleMotionRouting, } = routeUpdateActions + const { homeExceptPlungers } = recoveryCommands const { selectedRecoveryOption } = currentRecoveryOptionUtils const { MANUAL_MOVE_AND_SKIP, @@ -48,24 +51,29 @@ export function GripperIsHoldingLabware({ const { t } = useTranslation(['error_recovery', 'shared']) const handleNoOption = (): void => { - switch (selectedRecoveryOption) { - case MANUAL_MOVE_AND_SKIP.ROUTE: - void proceedToRouteAndStep( - MANUAL_MOVE_AND_SKIP.ROUTE, - MANUAL_MOVE_AND_SKIP.STEPS.MANUAL_MOVE - ) - break - case MANUAL_REPLACE_AND_RETRY.ROUTE: - void proceedToRouteAndStep( - MANUAL_REPLACE_AND_RETRY.ROUTE, - MANUAL_REPLACE_AND_RETRY.STEPS.MANUAL_REPLACE - ) - break - default: { - console.error('Unexpected recovery option for gripper routing.') - void proceedToRouteAndStep(OPTION_SELECTION.ROUTE) - } - } + // The "yes" option also contains a home, but it occurs later in the control flow, + // after the user has extricated the labware from the gripper jaws. + void handleMotionRouting(true) + .then(() => homeExceptPlungers()) + .finally(() => handleMotionRouting(false)) + .then(() => { + switch (selectedRecoveryOption) { + case MANUAL_MOVE_AND_SKIP.ROUTE: + return proceedToRouteAndStep( + MANUAL_MOVE_AND_SKIP.ROUTE, + MANUAL_MOVE_AND_SKIP.STEPS.MANUAL_MOVE + ) + case MANUAL_REPLACE_AND_RETRY.ROUTE: + return proceedToRouteAndStep( + MANUAL_REPLACE_AND_RETRY.ROUTE, + MANUAL_REPLACE_AND_RETRY.STEPS.MANUAL_REPLACE + ) + default: { + console.error('Unexpected recovery option for gripper routing.') + return proceedToRouteAndStep(OPTION_SELECTION.ROUTE) + } + } + }) } const primaryOnClick = (): void => { diff --git a/app/src/organisms/ErrorRecoveryFlows/shared/RecoveryInterventionModal.tsx b/app/src/organisms/ErrorRecoveryFlows/shared/RecoveryInterventionModal.tsx index 73ac8497deb..cba8719e376 100644 --- a/app/src/organisms/ErrorRecoveryFlows/shared/RecoveryInterventionModal.tsx +++ b/app/src/organisms/ErrorRecoveryFlows/shared/RecoveryInterventionModal.tsx @@ -38,7 +38,7 @@ export function RecoveryInterventionModal({ } return createPortal( - + ) => { let mockProceedToRouteAndStep: Mock let mockProceedNextStep: Mock +let mockHandleMotionRouting: Mock +let mockHomeExceptPlungers: Mock describe('GripperIsHoldingLabware', () => { let props: ComponentProps beforeEach(() => { mockProceedToRouteAndStep = vi.fn(() => Promise.resolve()) mockProceedNextStep = vi.fn(() => Promise.resolve()) + mockHandleMotionRouting = vi.fn(() => Promise.resolve()) + mockHomeExceptPlungers = vi.fn(() => Promise.resolve()) props = { ...mockRecoveryContentProps, routeUpdateActions: { proceedToRouteAndStep: mockProceedToRouteAndStep, proceedNextStep: mockProceedNextStep, + handleMotionRouting: mockHandleMotionRouting, } as any, + recoveryCommands: { homeExceptPlungers: mockHomeExceptPlungers } as any, } }) @@ -82,6 +88,18 @@ describe('GripperIsHoldingLabware', () => { fireEvent.click(screen.getAllByLabelText('No')[0]) clickButtonLabeled('Continue') + await waitFor(() => { + expect(mockHandleMotionRouting).toHaveBeenCalledWith(true) + }) + + await waitFor(() => { + expect(mockHomeExceptPlungers).toHaveBeenCalled() + }) + + await waitFor(() => { + expect(mockHandleMotionRouting).toHaveBeenCalledWith(false) + }) + await waitFor(() => { expect(mockProceedToRouteAndStep).toHaveBeenCalledWith( RECOVERY_MAP.MANUAL_MOVE_AND_SKIP.ROUTE, diff --git a/app/src/organisms/ErrorRecoveryFlows/shared/__tests__/RetryStepInfo.test.tsx b/app/src/organisms/ErrorRecoveryFlows/shared/__tests__/RetryStepInfo.test.tsx index 810cf1c00f1..90ae937dd24 100644 --- a/app/src/organisms/ErrorRecoveryFlows/shared/__tests__/RetryStepInfo.test.tsx +++ b/app/src/organisms/ErrorRecoveryFlows/shared/__tests__/RetryStepInfo.test.tsx @@ -108,8 +108,8 @@ describe('RetryStepInfo', () => { render(props) screen.getByText( - 'First, take any necessary actions to prepare the robot to retry the failed step.' + 'Take any necessary additional actions to prepare the robot to retry the failed step.' ) - screen.getByText('Then, close the robot door before proceeding.') + screen.getByText('Close the robot door before proceeding.') }) }) diff --git a/app/src/organisms/GripperWizardFlows/index.tsx b/app/src/organisms/GripperWizardFlows/index.tsx index 1a4bab512eb..17b61ab51c8 100644 --- a/app/src/organisms/GripperWizardFlows/index.tsx +++ b/app/src/organisms/GripperWizardFlows/index.tsx @@ -145,6 +145,8 @@ export function GripperWizardFlows( }) const handleCleanUpAndClose = (): void => { + setIsExiting(true) + if (maintenanceRunData?.data.id == null) { handleClose() } else { diff --git a/app/src/organisms/ODD/QuickTransferFlow/constants.ts b/app/src/organisms/ODD/QuickTransferFlow/constants.ts index dd1b18cda43..5aa6aa3b60d 100644 --- a/app/src/organisms/ODD/QuickTransferFlow/constants.ts +++ b/app/src/organisms/ODD/QuickTransferFlow/constants.ts @@ -100,6 +100,7 @@ export const SINGLE_CHANNEL_COMPATIBLE_LABWARE = [ 'opentrons/thermoscientificnunc_96_wellplate_2000ul/1', 'opentrons/usascientific_12_reservoir_22ml/1', 'opentrons/usascientific_96_wellplate_2.4ml_deep/1', + 'opentrons/evotips_opentrons_96_labware/1', ] export const EIGHT_CHANNEL_COMPATIBLE_LABWARE = [ @@ -144,6 +145,7 @@ export const EIGHT_CHANNEL_COMPATIBLE_LABWARE = [ 'opentrons/thermoscientificnunc_96_wellplate_2000ul/1', 'opentrons/usascientific_12_reservoir_22ml/1', 'opentrons/usascientific_96_wellplate_2.4ml_deep/1', + 'opentrons/evotips_opentrons_96_labware/1', ] export const NINETY_SIX_CHANNEL_COMPATIBLE_LABWARE = [ @@ -188,4 +190,5 @@ export const NINETY_SIX_CHANNEL_COMPATIBLE_LABWARE = [ 'opentrons/thermoscientificnunc_96_wellplate_2000ul/1', 'opentrons/usascientific_12_reservoir_22ml/1', 'opentrons/usascientific_96_wellplate_2.4ml_deep/1', + 'opentrons/evotips_opentrons_96_labware/1', ] diff --git a/app/src/organisms/ODD/RobotDashboard/RecentRunProtocolCard.tsx b/app/src/organisms/ODD/RobotDashboard/RecentRunProtocolCard.tsx index e522fb1dae7..a91bb4fbda1 100644 --- a/app/src/organisms/ODD/RobotDashboard/RecentRunProtocolCard.tsx +++ b/app/src/organisms/ODD/RobotDashboard/RecentRunProtocolCard.tsx @@ -158,15 +158,22 @@ export function ProtocolWithLastRun({ [RUN_STATUS_SUCCEEDED]: t('completed'), [RUN_STATUS_FAILED]: t('failed'), } - // TODO(BC, 2023-06-05): see if addSuffix false allow can remove usage of .replace here - const formattedLastRunTime = formatDistance( - // Fallback to current date if completedAt is null, though this should never happen since runs must be completed to appear in dashboard - new Date(runData.completedAt ?? new Date()), - new Date(), - { - addSuffix: true, + const formattedLastRunTime = + runData.completedAt != null + ? formatDistance(new Date(runData.completedAt), new Date(), { + addSuffix: true, + }).replace('about ', '') + : null + const buildLastRunCopy = (): string => { + if (formattedLastRunTime != null) { + return i18n.format( + `${terminationTypeMap[runData.status] ?? ''} ${formattedLastRunTime}`, + 'capitalize' + ) + } else { + return '' } - ).replace('about ', '') + } return isProtocolFetching || isLookingForHardware ? ( - {i18n.format( - `${terminationTypeMap[runData.status] ?? ''} ${formattedLastRunTime}`, - 'capitalize' - )} + {buildLastRunCopy()} ) diff --git a/app/src/organisms/ODD/RunningProtocol/ConfirmCancelRunModal.tsx b/app/src/organisms/ODD/RunningProtocol/ConfirmCancelRunModal.tsx index 453e3152ad4..13e3e08885d 100644 --- a/app/src/organisms/ODD/RunningProtocol/ConfirmCancelRunModal.tsx +++ b/app/src/organisms/ODD/RunningProtocol/ConfirmCancelRunModal.tsx @@ -112,7 +112,7 @@ export function ConfirmCancelRunModal({ setShowConfirmCancelRunModal(false) }} > - + - + {t('branded:confirm_terminate')} @@ -79,6 +79,7 @@ export function TakeoverModal(props: TakeoverModalProps): JSX.Element { gridGap={SPACING.spacing40} alignItems={ALIGN_CENTER} justifyContent={ALIGN_CENTER} + width="100%" > { + const { t, i18n } = useTranslation('protocol_details') return ( ({ - text: option, + text: i18n.format(t(option), 'capitalize'), onClick: () => { setCurrentOption(option) }, @@ -266,7 +267,7 @@ const ProtocolSectionContent = ({ let protocolSection: JSX.Element | null = null switch (currentOption) { - case 'Summary': + case 'summary': protocolSection = ( ) break - case 'Parameters': + case 'parameters': protocolSection = break - case 'Hardware': + case 'hardware': protocolSection = break - case 'Labware': + case 'labware': protocolSection = break - case 'Liquids': + case 'liquids': protocolSection = break - case 'Deck': + case 'deck': protocolSection = break } return ( {protocolSection} diff --git a/app/src/pages/ODD/ProtocolSetup/ConfirmSetupStepsCompleteModal.tsx b/app/src/pages/ODD/ProtocolSetup/ConfirmSetupStepsCompleteModal.tsx index eafffd9a8f0..82c87c9f44f 100644 --- a/app/src/pages/ODD/ProtocolSetup/ConfirmSetupStepsCompleteModal.tsx +++ b/app/src/pages/ODD/ProtocolSetup/ConfirmSetupStepsCompleteModal.tsx @@ -36,7 +36,11 @@ export function ConfirmSetupStepsCompleteModal({ return ( - + {t('you_havent_confirmed', { missingSteps: new Intl.ListFormat('en', { diff --git a/app/src/pages/ODD/QuickTransferDetails/index.tsx b/app/src/pages/ODD/QuickTransferDetails/index.tsx index 37131176b3f..64b410e084d 100644 --- a/app/src/pages/ODD/QuickTransferDetails/index.tsx +++ b/app/src/pages/ODD/QuickTransferDetails/index.tsx @@ -180,10 +180,10 @@ const QuickTransferHeader = ({ } const transferSectionTabOptions = [ - 'Summary', - 'Hardware', - 'Labware', - 'Deck', + 'summary', + 'hardware', + 'labware', + 'deck', ] as const type TabOption = typeof transferSectionTabOptions[number] @@ -197,13 +197,14 @@ const TransferSectionTabs = ({ currentOption, setCurrentOption, }: TransferSectionTabsProps): JSX.Element => { + const { t, i18n } = useTranslation('protocol_details') const options = transferSectionTabOptions return ( ({ - text: option, + text: i18n.format(t(option), 'capitalize'), onClick: () => { setCurrentOption(option) }, @@ -263,7 +264,7 @@ const TransferSectionContent = ({ let protocolSection: JSX.Element | null = null switch (currentOption) { - case 'Summary': + case 'summary': protocolSection = ( ) break - case 'Hardware': + case 'hardware': protocolSection = break - case 'Labware': + case 'labware': protocolSection = break - case 'Deck': + case 'deck': protocolSection = break } return ( {protocolSection} diff --git a/app/src/pages/ODD/RobotSettingsDashboard/RobotSettingsList.tsx b/app/src/pages/ODD/RobotSettingsDashboard/RobotSettingsList.tsx index 2a878cf7e16..14e6f33e0b7 100644 --- a/app/src/pages/ODD/RobotSettingsDashboard/RobotSettingsList.tsx +++ b/app/src/pages/ODD/RobotSettingsDashboard/RobotSettingsList.tsx @@ -20,7 +20,7 @@ import { TYPOGRAPHY, } from '@opentrons/components' -import { LANGUAGES } from '/app/i18n' +import { LANGUAGES, US_ENGLISH_DISPLAY_NAME } from '/app/i18n' import { getLocalRobot, getRobotApiVersion } from '/app/redux/discovery' import { getRobotUpdateAvailable } from '/app/redux/robot-update' import { useErrorRecoverySettingsToggle } from '/app/resources/errorRecovery' @@ -146,7 +146,9 @@ export function RobotSettingsList(props: RobotSettingsListProps): JSX.Element { { setCurrentOption('LanguageSetting') diff --git a/app/src/pages/ODD/RunSummary/index.tsx b/app/src/pages/ODD/RunSummary/index.tsx index 86aec6aaf87..57c6ffe96ee 100644 --- a/app/src/pages/ODD/RunSummary/index.tsx +++ b/app/src/pages/ODD/RunSummary/index.tsx @@ -39,6 +39,7 @@ import { useProtocolQuery, useDeleteRunMutation, useRunCommandErrors, + useErrorRecoverySettings, } from '@opentrons/react-api-client' import { useRunControls } from '/app/organisms/RunTimeControl/hooks' import { onDeviceDisplayFormatTimestamp } from '/app/transformations/runs' @@ -68,8 +69,8 @@ import { useCurrentRunCommands, } from '/app/resources/runs' import { handleTipsAttachedModal } from '/app/organisms/DropTipWizardFlows' -import { lastRunCommandPromptedErrorRecovery } from '/app/local-resources/commands' import { useTipAttachmentStatus } from '/app/resources/instruments' +import { lastRunCommandPromptedErrorRecovery } from '/app/local-resources/commands' import type { IconName } from '@opentrons/components' import type { OnDeviceRouteParams } from '/app/App/types' @@ -235,22 +236,19 @@ export function RunSummary(): JSX.Element { runId, runRecord: runRecord ?? null, }) - - // Determine tip status on initial render only. Error Recovery always handles tip status, so don't show it twice. + const { data } = useErrorRecoverySettings() + const isEREnabled = data?.data.enabled ?? true const runSummaryNoFixit = useCurrentRunCommands({ includeFixitCommands: false, pageLength: 1, }) + useEffect(() => { - if ( - isRunCurrent && - runSummaryNoFixit != null && - runSummaryNoFixit.length > 0 && - !lastRunCommandPromptedErrorRecovery(runSummaryNoFixit) - ) { + // Only run tip checking if it wasn't *just* handled during Error Recovery. + if (!lastRunCommandPromptedErrorRecovery(runSummaryNoFixit, isEREnabled)) { void determineTipStatus() } - }, [runSummaryNoFixit, isRunCurrent]) + }, [isRunCurrent, runSummaryNoFixit, isEREnabled]) const returnToQuickTransfer = (): void => { closeCurrentRunIfValid(() => { diff --git a/app/src/pages/ODD/RunningProtocol/__tests__/RunningProtocol.test.tsx b/app/src/pages/ODD/RunningProtocol/__tests__/RunningProtocol.test.tsx index 33d6f79e9a7..cbb45387a5a 100644 --- a/app/src/pages/ODD/RunningProtocol/__tests__/RunningProtocol.test.tsx +++ b/app/src/pages/ODD/RunningProtocol/__tests__/RunningProtocol.test.tsx @@ -161,6 +161,7 @@ describe('RunningProtocol', () => { vi.mocked(useErrorRecoveryFlows).mockReturnValue({ isERActive: false, failedCommand: {} as any, + runLwDefsByUri: {} as any, }) vi.mocked(useInterventionModal).mockReturnValue({ showModal: false, @@ -224,6 +225,7 @@ describe('RunningProtocol', () => { vi.mocked(useErrorRecoveryFlows).mockReturnValue({ isERActive: true, failedCommand: {} as any, + runLwDefsByUri: {} as any, }) render(`/runs/${RUN_ID}/run`) screen.getByText('MOCK ERROR RECOVERY') diff --git a/app/src/pages/ODD/RunningProtocol/index.tsx b/app/src/pages/ODD/RunningProtocol/index.tsx index 234fbed317f..e34e0dc929c 100644 --- a/app/src/pages/ODD/RunningProtocol/index.tsx +++ b/app/src/pages/ODD/RunningProtocol/index.tsx @@ -122,7 +122,10 @@ export function RunningProtocol(): JSX.Element { const { trackProtocolRunEvent } = useTrackProtocolRunEvent(runId, robotName) const robotAnalyticsData = useRobotAnalyticsData(robotName) const robotType = useRobotType(robotName) - const { isERActive, failedCommand } = useErrorRecoveryFlows(runId, runStatus) + const { isERActive, failedCommand, runLwDefsByUri } = useErrorRecoveryFlows( + runId, + runStatus + ) const { showModal: showIntervention, modalProps: interventionProps, @@ -169,6 +172,7 @@ export function RunningProtocol(): JSX.Element { runStatus={runStatus} runId={runId} unvalidatedFailedCommand={failedCommand} + runLwDefsByUri={runLwDefsByUri} protocolAnalysis={robotSideAnalysis} /> ) : null} diff --git a/app/src/redux/config/__tests__/selectors.test.ts b/app/src/redux/config/__tests__/selectors.test.ts index 18262108c0a..00ac8f42ed3 100644 --- a/app/src/redux/config/__tests__/selectors.test.ts +++ b/app/src/redux/config/__tests__/selectors.test.ts @@ -246,7 +246,7 @@ describe('shell selectors', () => { sleepMs: 25200000, brightness: 4, textSize: 1, - unfinishedUnboxingFlowRoute: '/welcome', + unfinishedUnboxingFlowRoute: '/choose-language', }, }, } as any @@ -254,7 +254,7 @@ describe('shell selectors', () => { sleepMs: 25200000, brightness: 4, textSize: 1, - unfinishedUnboxingFlowRoute: '/welcome', + unfinishedUnboxingFlowRoute: '/choose-language', }) }) }) diff --git a/app/src/redux/config/schema-types.ts b/app/src/redux/config/schema-types.ts index e50a01d78ef..a917bdbb3dd 100644 --- a/app/src/redux/config/schema-types.ts +++ b/app/src/redux/config/schema-types.ts @@ -285,4 +285,8 @@ export type ConfigV25 = Omit & { } } -export type Config = ConfigV25 +export type ConfigV26 = Omit & { + version: 26 +} + +export type Config = ConfigV26 diff --git a/app/src/resources/runs/useRunLoadedLabwareDefinitionsByUri.ts b/app/src/resources/runs/useRunLoadedLabwareDefinitionsByUri.ts index d7ffb086d10..9a785cb99df 100644 --- a/app/src/resources/runs/useRunLoadedLabwareDefinitionsByUri.ts +++ b/app/src/resources/runs/useRunLoadedLabwareDefinitionsByUri.ts @@ -18,23 +18,29 @@ export type RunLoadedLabwareDefinitionsByUri = Record< // Returns a record of labware definitions keyed by URI for the labware that // has been loaded with a "loadLabware" command. Errors if the run is not the current run. +// Returns null if the network request is pending. export function useRunLoadedLabwareDefinitionsByUri( runId: string | null, options: UseQueryOptions = {}, hostOverride?: HostConfig -): RunLoadedLabwareDefinitionsByUri { +): RunLoadedLabwareDefinitionsByUri | null { const { data } = useRunLoadedLabwareDefinitions(runId, options, hostOverride) return useMemo(() => { const result: Record = {} - // @ts-expect-error TODO(jh, 10-12-24): Update the app's typing to support LabwareDefinition3. - data?.data.forEach((def: LabwareDefinition2) => { - if ('schemaVersion' in def) { - const lwUri = getLabwareDefURI(def) - result[lwUri] = def - } - }) - return result + if (data == null) { + return null + } else { + // @ts-expect-error TODO(jh, 10-12-24): Update the app's typing to support LabwareDefinition3. + data?.data.forEach((def: LabwareDefinition2) => { + if ('schemaVersion' in def) { + const lwUri = getLabwareDefURI(def) + result[lwUri] = def + } + }) + + return result + } }, [data]) } diff --git a/components/src/hardware-sim/Deck/MoveLabwareOnDeck.tsx b/components/src/hardware-sim/Deck/MoveLabwareOnDeck.tsx index a41e99c1036..96149de5fee 100644 --- a/components/src/hardware-sim/Deck/MoveLabwareOnDeck.tsx +++ b/components/src/hardware-sim/Deck/MoveLabwareOnDeck.tsx @@ -38,7 +38,7 @@ const getModulePosition = ( ) if (modSlot == null) return null - const modPosition = getPositionFromSlotId(loadedModule.id, deckDef) + const modPosition = getPositionFromSlotId(modSlot.id, deckDef) if (modPosition == null) return null const [modX, modY] = modPosition diff --git a/components/src/organisms/CommandText/useCommandTextString/index.ts b/components/src/organisms/CommandText/useCommandTextString/index.ts index 01754c0e71e..3d4fbdfeeff 100644 --- a/components/src/organisms/CommandText/useCommandTextString/index.ts +++ b/components/src/organisms/CommandText/useCommandTextString/index.ts @@ -93,6 +93,9 @@ export function useCommandTextString( case 'dropTipInPlace': case 'pickUpTip': case 'airGapInPlace': + case 'evotipSealPipette': + case 'evotipUnsealPipette': + case 'evotipDispense': return { kind: 'generic', commandText: utils.getPipettingCommandText(fullParams), diff --git a/components/src/organisms/CommandText/useCommandTextString/utils/commandText/getPipettingCommandText.ts b/components/src/organisms/CommandText/useCommandTextString/utils/commandText/getPipettingCommandText.ts index bd4b020d8eb..851aca53be5 100644 --- a/components/src/organisms/CommandText/useCommandTextString/utils/commandText/getPipettingCommandText.ts +++ b/components/src/organisms/CommandText/useCommandTextString/utils/commandText/getPipettingCommandText.ts @@ -48,19 +48,21 @@ export const getPipettingCommandText = ({ t, }) + const labwareName = + commandTextData != null + ? getLabwareName({ + loadedLabwares: commandTextData.labware ?? [], + labwareId, + allRunDefs, + }) + : null + switch (command?.commandType) { case 'aspirate': { const { volume, flowRate } = command.params return t('aspirate', { well_name: wellName, - labware: - commandTextData != null - ? getLabwareName({ - loadedLabwares: commandTextData.labware ?? [], - labwareId, - allRunDefs, - }) - : null, + labware: labwareName, labware_location: displayLocation, volume, flow_rate: flowRate, @@ -71,14 +73,7 @@ export const getPipettingCommandText = ({ return pushOut != null ? t('dispense_push_out', { well_name: wellName, - labware: - commandTextData != null - ? getLabwareName({ - loadedLabwares: commandTextData.labware ?? [], - labwareId, - allRunDefs, - }) - : null, + labware: labwareName, labware_location: displayLocation, volume, flow_rate: flowRate, @@ -86,14 +81,7 @@ export const getPipettingCommandText = ({ }) : t('dispense', { well_name: wellName, - labware: - commandTextData != null - ? getLabwareName({ - loadedLabwares: commandTextData.labware ?? [], - labwareId, - allRunDefs, - }) - : null, + labware: labwareName, labware_location: displayLocation, volume, flow_rate: flowRate, @@ -103,14 +91,7 @@ export const getPipettingCommandText = ({ const { flowRate } = command.params return t('blowout', { well_name: wellName, - labware: - commandTextData != null - ? getLabwareName({ - loadedLabwares: commandTextData.labware ?? [], - labwareId, - allRunDefs, - }) - : null, + labware: labwareName, labware_location: displayLocation, flow_rate: flowRate, }) @@ -132,26 +113,12 @@ export const getPipettingCommandText = ({ return Boolean(labwareDef?.parameters.isTiprack) ? t('return_tip', { well_name: wellName, - labware: - commandTextData != null - ? getLabwareName({ - loadedLabwares: commandTextData.labware ?? [], - labwareId, - allRunDefs, - }) - : null, + labware: labwareName, labware_location: displayLocation, }) : t('drop_tip', { well_name: wellName, - labware: - commandTextData != null - ? getLabwareName({ - loadedLabwares: commandTextData.labware ?? [], - labwareId, - allRunDefs, - }) - : null, + labware: labwareName, }) } case 'pickUpTip': { @@ -172,14 +139,7 @@ export const getPipettingCommandText = ({ pipetteName ) : null, - labware: - commandTextData != null - ? getLabwareName({ - loadedLabwares: commandTextData.labware ?? [], - labwareId, - allRunDefs, - }) - : null, + labware: labwareName, labware_location: displayLocation, }) } @@ -209,6 +169,22 @@ export const getPipettingCommandText = ({ const { volume } = command.params return t('air_gap_in_place', { volume }) } + case 'evotipSealPipette': { + return t('sealing_to_location', { + labware: labwareName, + location: displayLocation, + }) + } + case 'evotipUnsealPipette': { + return t('unsealing_from_location', { + labware: labwareName, + location: displayLocation, + }) + } + case 'evotipDispense': { + const { flowRate, volume } = command.params + return t('pressurizing_to_dispense', { volume, flow_rate: flowRate }) + } default: { console.warn( 'PipettingCommandText encountered a command with an unrecognized commandType: ', diff --git a/hardware-testing/hardware_testing/production_qc/gripper_assembly_qc_ot3/test_mount.py b/hardware-testing/hardware_testing/production_qc/gripper_assembly_qc_ot3/test_mount.py index 7d0855e54b4..df40b60e61f 100644 --- a/hardware-testing/hardware_testing/production_qc/gripper_assembly_qc_ot3/test_mount.py +++ b/hardware-testing/hardware_testing/production_qc/gripper_assembly_qc_ot3/test_mount.py @@ -120,7 +120,7 @@ async def _save_result(tag: str, target_z: float, include_pass_fail: bool) -> bo mount, Point(z=-Z_AXIS_TRAVEL_DISTANCE), speed=speed, - _expect_stalls=True, + expect_stalls=True, ) down_end_passed = await _save_result( _get_test_tag(current, speed, "down", "end"), @@ -139,7 +139,7 @@ async def _save_result(tag: str, target_z: float, include_pass_fail: bool) -> bo mount, Point(z=Z_AXIS_TRAVEL_DISTANCE), speed=speed, - _expect_stalls=True, + expect_stalls=True, ) up_end_passed = await _save_result( _get_test_tag(current, speed, "up", "end"), diff --git a/hardware-testing/hardware_testing/production_qc/robot_assembly_qc_ot3/test_instruments.py b/hardware-testing/hardware_testing/production_qc/robot_assembly_qc_ot3/test_instruments.py index a9a86cc6d9b..ef169914ba9 100644 --- a/hardware-testing/hardware_testing/production_qc/robot_assembly_qc_ot3/test_instruments.py +++ b/hardware-testing/hardware_testing/production_qc/robot_assembly_qc_ot3/test_instruments.py @@ -201,10 +201,10 @@ async def _test_gripper(api: OT3API, report: CSVReport, section: str) -> None: target_z = 100 await api.home([z_ax, Axis.G]) start_pos = await api.gantry_position(OT3Mount.GRIPPER) - await api.move_to(mount, start_pos._replace(z=target_z), _expect_stalls=True) + await api.move_to(mount, start_pos._replace(z=target_z), expect_stalls=True) enc_pos = await api.encoder_current_position_ot3(OT3Mount.GRIPPER) if abs(enc_pos[Axis.Z_G] - target_z) < 0.25: - await api.move_to(mount, start_pos, _expect_stalls=True) + await api.move_to(mount, start_pos, expect_stalls=True) if abs(enc_pos[Axis.Z_G] - target_z) < 0.25: result = CSVResult.PASS await api.home([z_ax]) diff --git a/hardware-testing/hardware_testing/production_qc/z_stage_qc_ot3.py b/hardware-testing/hardware_testing/production_qc/z_stage_qc_ot3.py index 8a55a831c45..3ec704686c1 100644 --- a/hardware-testing/hardware_testing/production_qc/z_stage_qc_ot3.py +++ b/hardware-testing/hardware_testing/production_qc/z_stage_qc_ot3.py @@ -259,7 +259,7 @@ async def _force_gauge( mount=mount, abs_position=press_pos, speed=FORCE_SPEED, - _expect_stalls=True, + expect_stalls=True, ) finally: thread_sensor = False diff --git a/hardware-testing/hardware_testing/protocols/liquid_sense/lld_test_empty_wells.py b/hardware-testing/hardware_testing/protocols/liquid_sense/lld_test_empty_wells.py index 9dafa3a9803..2e289eed919 100644 --- a/hardware-testing/hardware_testing/protocols/liquid_sense/lld_test_empty_wells.py +++ b/hardware-testing/hardware_testing/protocols/liquid_sense/lld_test_empty_wells.py @@ -114,7 +114,7 @@ def _setup( major=int(pip_model_list[-1][-3]), # type: ignore[arg-type] minor=int(pip_model_list[-1][-1]), # type: ignore[arg-type] ), - oem=PipetteOEMType.EM if "em" in pipette.model else PipetteOEMType.OT, + oem=PipetteOEMType.get_oem_from_model_str(str(pipette.model)), ) # Writes details about test run to google sheet. tipVolume = "t" + str(TIP_SIZE) diff --git a/hardware/opentrons_hardware/drivers/can_bus/can_messenger.py b/hardware/opentrons_hardware/drivers/can_bus/can_messenger.py index 69623381d96..c9adc2fc9b9 100644 --- a/hardware/opentrons_hardware/drivers/can_bus/can_messenger.py +++ b/hardware/opentrons_hardware/drivers/can_bus/can_messenger.py @@ -153,7 +153,7 @@ async def send_and_verify_recieved(self) -> ErrorCode: ) except asyncio.TimeoutError: log.error( - f"Message did not receive ack for message index {self._message.payload.message_index}" + f"Message did not receive ack for message index {self._message.payload.message_index} Missing node(s) {self._expected_nodes}" ) return ErrorCode.timeout finally: @@ -279,12 +279,14 @@ async def _ensure_send( exclusive: bool = False, ) -> ErrorCode: if len(expected_nodes) == 0: - log.warning("Expected Nodes should have been specified") if node_id == NodeId.broadcast: if not expected_nodes: expected_nodes = list(self._known_nodes) else: expected_nodes = [node_id] + log.warning( + f"Expected Nodes should have been specified, Setting expected nodes to {expected_nodes}" + ) listener = AcknowledgeListener( can_messenger=self, diff --git a/hardware/opentrons_hardware/hardware_control/move_group_runner.py b/hardware/opentrons_hardware/hardware_control/move_group_runner.py index 1b7baf61d6d..9d9ff583ec7 100644 --- a/hardware/opentrons_hardware/hardware_control/move_group_runner.py +++ b/hardware/opentrons_hardware/hardware_control/move_group_runner.py @@ -469,6 +469,10 @@ def _remove_move_group( f"Received completion for {node_id} group {group_id} seq {seq_id}" f", which {'is' if in_group else 'isn''t'} in group" ) + if self._moves[group_id] and len(self._moves[group_id]) == 0: + log.error( + f"Python bug proven if check {bool(not self._moves[group_id])} len check {len(self._moves[group_id]) == 0}" + ) if not self._moves[group_id]: log.debug(f"Move group {group_id+self._start_at_index} has completed.") self._event.set() diff --git a/robot-server/robot_server/labware_offsets/router.py b/robot-server/robot_server/labware_offsets/router.py index e75bb27d926..3f0ada1d46e 100644 --- a/robot-server/robot_server/labware_offsets/router.py +++ b/robot-server/robot_server/labware_offsets/router.py @@ -52,6 +52,7 @@ """ ), status_code=201, + include_in_schema=False, # todo(mm, 2025-01-08): Include for v8.4.0. ) async def post_labware_offset( # noqa: D103 store: Annotated[LabwareOffsetStore, fastapi.Depends(get_labware_offset_store)], @@ -82,6 +83,7 @@ async def post_labware_offset( # noqa: D103 " Filters are ANDed together." " Results are returned in order from oldest to newest." ), + include_in_schema=False, # todo(mm, 2025-01-08): Include for v8.4.0. ) async def get_labware_offsets( # noqa: D103 store: Annotated[LabwareOffsetStore, fastapi.Depends(get_labware_offset_store)], @@ -173,6 +175,7 @@ async def get_labware_offsets( # noqa: D103 path="/labwareOffsets/{id}", summary="Delete a single labware offset", description="Delete a single labware offset. The deleted offset is returned.", + include_in_schema=False, # todo(mm, 2025-01-08): Include for v8.4.0. ) async def delete_labware_offset( # noqa: D103 store: Annotated[LabwareOffsetStore, fastapi.Depends(get_labware_offset_store)], @@ -195,6 +198,7 @@ async def delete_labware_offset( # noqa: D103 router.delete, path="/labwareOffsets", summary="Delete all labware offsets", + include_in_schema=False, # todo(mm, 2025-01-08): Include for v8.4.0. ) async def delete_all_labware_offsets( # noqa: D103 store: Annotated[LabwareOffsetStore, fastapi.Depends(get_labware_offset_store)] diff --git a/robot-server/robot_server/service/legacy/routers/networking.py b/robot-server/robot_server/service/legacy/routers/networking.py index ea3c4543ea8..d0acb1b64be 100644 --- a/robot-server/robot_server/service/legacy/routers/networking.py +++ b/robot-server/robot_server/service/legacy/routers/networking.py @@ -1,5 +1,6 @@ import logging import os +import re import subprocess from typing import Annotated, Optional @@ -96,6 +97,13 @@ async def get_wifi_networks( return WifiNetworks(list=[WifiNetworkFull(**n) for n in networks]) +def _massage_nmcli_error(error_string: str) -> str: + """Raises a better-formatted error message from an nmcli error string.""" + if re.search("password.*802-11-wireless-security\\.psk.*not given", error_string): + return "Could not connect to network. Please double-check network credentials." + return error_string + + @router.post( path="/wifi/configure", summary="Configure the robot's Wi-Fi", @@ -129,7 +137,8 @@ async def post_wifi_configure( if not ok: raise LegacyErrorResponse( - message=message, errorCode=ErrorCodes.GENERAL_ERROR.value.code + message=_massage_nmcli_error(message), + errorCode=ErrorCodes.GENERAL_ERROR.value.code, ).as_error(status.HTTP_401_UNAUTHORIZED) return WifiConfigurationResponse(message=message, ssid=configuration.ssid) diff --git a/robot-server/tests/service/legacy/routers/test_networking.py b/robot-server/tests/service/legacy/routers/test_networking.py index 22ea2359a92..ebc42a41839 100755 --- a/robot-server/tests/service/legacy/routers/test_networking.py +++ b/robot-server/tests/service/legacy/routers/test_networking.py @@ -5,6 +5,7 @@ import pytest from opentrons.system import nmcli, wifi +from robot_server.service.legacy.routers.networking import _massage_nmcli_error from typing import Optional @@ -369,3 +370,25 @@ def check_option(opt_dict): assert "options" in opt for method_opt in opt["options"]: check_option(method_opt) + + +@pytest.mark.parametrize( + "nmcli_message,result_message", + [ + ( + "Warning: password for '802-11-wireless-security.psk' not given in 'passwd-file' and nmcli cannot ask without '--ask' option. Error: Connection activation failed: Secrets were required, but not provided Hint: use 'journalctl -xe NM_CONNECTION=05d784ec-1feb4147-be22-c07d7915ef96 + NM_DEVICE=mlan0' to get more details.", + "Could not connect to network. Please double-check network credentials.", + ), + ( + "Warning: asdasdasff for '802-11-afasda' not given in 'asdadsa'. Error: Connection activation failed: Secrets were required, but not provided", + "Warning: asdasdasff for '802-11-afasda' not given in 'asdadsa'. Error: Connection activation failed: Secrets were required, but not provided", + ), + ( + "Error: Connection activation failed: Secrets were required, but not provided", + "Error: Connection activation failed: Secrets were required, but not provided", + ), + ], +) +def test_error_rewriting(nmcli_message: str, result_message: str) -> None: + """It should rewrite known nmcli failure messages.""" + assert _massage_nmcli_error(nmcli_message) == result_message diff --git a/shared-data/command/schemas/11.json b/shared-data/command/schemas/11.json index a6d9c39b768..3f3dc469293 100644 --- a/shared-data/command/schemas/11.json +++ b/shared-data/command/schemas/11.json @@ -1782,6 +1782,195 @@ "title": "EngageParams", "type": "object" }, + "EvotipDispenseCreate": { + "description": "DispenseInPlace command request model.", + "properties": { + "commandType": { + "const": "evotipDispense", + "default": "evotipDispense", + "enum": ["evotipDispense"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/EvotipDispenseParams" + } + }, + "required": ["params"], + "title": "EvotipDispenseCreate", + "type": "object" + }, + "EvotipDispenseParams": { + "description": "Payload required to dispense in place.", + "properties": { + "flowRate": { + "description": "Speed in \u00b5L/s configured for the pipette", + "exclusiveMinimum": 0.0, + "title": "Flowrate", + "type": "number" + }, + "labwareId": { + "description": "Identifier of labware to use.", + "title": "Labwareid", + "type": "string" + }, + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + }, + "volume": { + "description": "The amount of liquid to dispense, in \u00b5L. Must not be greater than the currently aspirated volume. There is some tolerance for floating point rounding errors.", + "minimum": 0.0, + "title": "Volume", + "type": "number" + }, + "wellLocation": { + "$ref": "#/$defs/LiquidHandlingWellLocation", + "description": "Relative well location at which to perform the operation" + }, + "wellName": { + "description": "Name of well to use in labware.", + "title": "Wellname", + "type": "string" + } + }, + "required": ["labwareId", "wellName", "flowRate", "volume", "pipetteId"], + "title": "EvotipDispenseParams", + "type": "object" + }, + "EvotipSealPipetteCreate": { + "description": "Seal evotip resin tip command creation request model.", + "properties": { + "commandType": { + "const": "evotipSealPipette", + "default": "evotipSealPipette", + "enum": ["evotipSealPipette"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/EvotipSealPipetteParams" + } + }, + "required": ["params"], + "title": "EvotipSealPipetteCreate", + "type": "object" + }, + "EvotipSealPipetteParams": { + "description": "Payload needed to seal resin tips to a pipette.", + "properties": { + "labwareId": { + "description": "Identifier of labware to use.", + "title": "Labwareid", + "type": "string" + }, + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + }, + "tipPickUpParams": { + "anyOf": [ + { + "$ref": "#/$defs/TipPickUpParams" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Specific parameters for " + }, + "wellLocation": { + "$ref": "#/$defs/PickUpTipWellLocation", + "description": "Relative well location at which to pick up the tip." + }, + "wellName": { + "description": "Name of well to use in labware.", + "title": "Wellname", + "type": "string" + } + }, + "required": ["pipetteId", "labwareId", "wellName"], + "title": "EvotipSealPipetteParams", + "type": "object" + }, + "EvotipUnsealPipetteCreate": { + "description": "Evotip unseal command creation request model.", + "properties": { + "commandType": { + "const": "evotipUnsealPipette", + "default": "evotipUnsealPipette", + "enum": ["evotipUnsealPipette"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/EvotipUnsealPipetteParams" + } + }, + "required": ["params"], + "title": "EvotipUnsealPipetteCreate", + "type": "object" + }, + "EvotipUnsealPipetteParams": { + "description": "Payload required to drop a tip in a specific well.", + "properties": { + "labwareId": { + "description": "Identifier of labware to use.", + "title": "Labwareid", + "type": "string" + }, + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + }, + "wellLocation": { + "$ref": "#/$defs/DropTipWellLocation", + "description": "Relative well location at which to drop the tip." + }, + "wellName": { + "description": "Name of well to use in labware.", + "title": "Wellname", + "type": "string" + } + }, + "required": ["pipetteId", "labwareId", "wellName"], + "title": "EvotipUnsealPipetteParams", + "type": "object" + }, "GetNextTipCreate": { "description": "Get next tip command creation request model.", "properties": { @@ -4873,6 +5062,31 @@ "title": "Submerge", "type": "object" }, + "TipPickUpParams": { + "description": "Payload used to specify press-tip parameters for a seal command.", + "properties": { + "ejectorPushMm": { + "default": 0, + "description": "The distance to back off to ensure that the tip presence sensors are not triggered.", + "title": "Ejectorpushmm", + "type": "number" + }, + "prepDistance": { + "default": 0, + "description": "The distance to move down to fit the tips on.", + "title": "Prepdistance", + "type": "number" + }, + "pressDistance": { + "default": 0, + "description": "The distance to press on tips.", + "title": "Pressdistance", + "type": "number" + } + }, + "title": "TipPickUpParams", + "type": "object" + }, "TipPresenceStatus": { "description": "Tip presence status reported by a pipette.", "enum": ["present", "absent", "unknown"], @@ -6035,6 +6249,9 @@ "flexStacker/configure": "#/$defs/ConfigureCreate", "flexStacker/retrieve": "#/$defs/RetrieveCreate", "flexStacker/store": "#/$defs/StoreCreate", + "evotipDispense": "#/$defs/EvotipDispenseCreate", + "evotipSealPipette": "#/$defs/EvotipSealPipetteCreate", + "evotipUnsealPipette": "#/$defs/EvotipUnsealPipetteCreate", "getNextTip": "#/$defs/GetNextTipCreate", "getTipPresence": "#/$defs/GetTipPresenceCreate", "heaterShaker/closeLabwareLatch": "#/$defs/CloseLabwareLatchCreate", @@ -6234,6 +6451,15 @@ { "$ref": "#/$defs/TryLiquidProbeCreate" }, + { + "$ref": "#/$defs/EvotipSealPipetteCreate" + }, + { + "$ref": "#/$defs/EvotipDispenseCreate" + }, + { + "$ref": "#/$defs/EvotipUnsealPipetteCreate" + }, { "$ref": "#/$defs/opentrons__protocol_engine__commands__heater_shaker__wait_for_temperature__WaitForTemperatureCreate" }, diff --git a/shared-data/command/schemas/12.json b/shared-data/command/schemas/12.json index 914e32a117b..2e40c357c7d 100644 --- a/shared-data/command/schemas/12.json +++ b/shared-data/command/schemas/12.json @@ -1880,6 +1880,209 @@ "title": "EngageParams", "type": "object" }, + "EvotipDispenseCreate": { + "description": "DispenseInPlace command request model.", + "properties": { + "commandType": { + "const": "evotipDispense", + "default": "evotipDispense", + "enum": ["evotipDispense"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/EvotipDispenseParams" + } + }, + "required": ["params"], + "title": "EvotipDispenseCreate", + "type": "object" + }, + "EvotipDispenseParams": { + "description": "Payload required to dispense in place.", + "properties": { + "correctionVolume": { + "anyOf": [ + { + "minimum": 0.0, + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The correction volume in uL.", + "title": "Correctionvolume" + }, + "flowRate": { + "description": "Speed in \u00b5L/s configured for the pipette", + "exclusiveMinimum": 0.0, + "title": "Flowrate", + "type": "number" + }, + "labwareId": { + "description": "Identifier of labware to use.", + "title": "Labwareid", + "type": "string" + }, + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + }, + "volume": { + "description": "The amount of liquid to dispense, in \u00b5L. Must not be greater than the currently aspirated volume. There is some tolerance for floating point rounding errors.", + "minimum": 0.0, + "title": "Volume", + "type": "number" + }, + "wellLocation": { + "$ref": "#/$defs/LiquidHandlingWellLocation", + "description": "Relative well location at which to perform the operation" + }, + "wellName": { + "description": "Name of well to use in labware.", + "title": "Wellname", + "type": "string" + } + }, + "required": ["labwareId", "wellName", "flowRate", "volume", "pipetteId"], + "title": "EvotipDispenseParams", + "type": "object" + }, + "EvotipSealPipetteCreate": { + "description": "Seal evotip resin tip command creation request model.", + "properties": { + "commandType": { + "const": "evotipSealPipette", + "default": "evotipSealPipette", + "enum": ["evotipSealPipette"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/EvotipSealPipetteParams" + } + }, + "required": ["params"], + "title": "EvotipSealPipetteCreate", + "type": "object" + }, + "EvotipSealPipetteParams": { + "description": "Payload needed to seal resin tips to a pipette.", + "properties": { + "labwareId": { + "description": "Identifier of labware to use.", + "title": "Labwareid", + "type": "string" + }, + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + }, + "tipPickUpParams": { + "anyOf": [ + { + "$ref": "#/$defs/TipPickUpParams" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Specific parameters for " + }, + "wellLocation": { + "$ref": "#/$defs/PickUpTipWellLocation", + "description": "Relative well location at which to pick up the tip." + }, + "wellName": { + "description": "Name of well to use in labware.", + "title": "Wellname", + "type": "string" + } + }, + "required": ["pipetteId", "labwareId", "wellName"], + "title": "EvotipSealPipetteParams", + "type": "object" + }, + "EvotipUnsealPipetteCreate": { + "description": "Evotip unseal command creation request model.", + "properties": { + "commandType": { + "const": "evotipUnsealPipette", + "default": "evotipUnsealPipette", + "enum": ["evotipUnsealPipette"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/EvotipUnsealPipetteParams" + } + }, + "required": ["params"], + "title": "EvotipUnsealPipetteCreate", + "type": "object" + }, + "EvotipUnsealPipetteParams": { + "description": "Payload required to drop a tip in a specific well.", + "properties": { + "labwareId": { + "description": "Identifier of labware to use.", + "title": "Labwareid", + "type": "string" + }, + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + }, + "wellLocation": { + "$ref": "#/$defs/DropTipWellLocation", + "description": "Relative well location at which to drop the tip." + }, + "wellName": { + "description": "Name of well to use in labware.", + "title": "Wellname", + "type": "string" + } + }, + "required": ["pipetteId", "labwareId", "wellName"], + "title": "EvotipUnsealPipetteParams", + "type": "object" + }, "GetNextTipCreate": { "description": "Get next tip command creation request model.", "properties": { @@ -4971,6 +5174,31 @@ "title": "Submerge", "type": "object" }, + "TipPickUpParams": { + "description": "Payload used to specify press-tip parameters for a seal command.", + "properties": { + "ejectorPushMm": { + "default": 0, + "description": "The distance to back off to ensure that the tip presence sensors are not triggered.", + "title": "Ejectorpushmm", + "type": "number" + }, + "prepDistance": { + "default": 0, + "description": "The distance to move down to fit the tips on.", + "title": "Prepdistance", + "type": "number" + }, + "pressDistance": { + "default": 0, + "description": "The distance to press on tips.", + "title": "Pressdistance", + "type": "number" + } + }, + "title": "TipPickUpParams", + "type": "object" + }, "TipPresenceStatus": { "description": "Tip presence status reported by a pipette.", "enum": ["present", "absent", "unknown"], @@ -6130,6 +6358,9 @@ "dispenseWhileTracking": "#/$defs/DispenseWhileTrackingCreate", "dropTip": "#/$defs/DropTipCreate", "dropTipInPlace": "#/$defs/DropTipInPlaceCreate", + "evotipDispense": "#/$defs/EvotipDispenseCreate", + "evotipSealPipette": "#/$defs/EvotipSealPipetteCreate", + "evotipUnsealPipette": "#/$defs/EvotipUnsealPipetteCreate", "flexStacker/configure": "#/$defs/ConfigureCreate", "flexStacker/retrieve": "#/$defs/RetrieveCreate", "flexStacker/store": "#/$defs/StoreCreate", @@ -6332,6 +6563,15 @@ { "$ref": "#/$defs/TryLiquidProbeCreate" }, + { + "$ref": "#/$defs/EvotipSealPipetteCreate" + }, + { + "$ref": "#/$defs/EvotipDispenseCreate" + }, + { + "$ref": "#/$defs/EvotipUnsealPipetteCreate" + }, { "$ref": "#/$defs/opentrons__protocol_engine__commands__heater_shaker__wait_for_temperature__WaitForTemperatureCreate" }, diff --git a/shared-data/command/types/pipetting.ts b/shared-data/command/types/pipetting.ts index d609af1854b..277af530ce9 100644 --- a/shared-data/command/types/pipetting.ts +++ b/shared-data/command/types/pipetting.ts @@ -21,6 +21,9 @@ export type PipettingRunTimeCommand = | LiquidProbeRunTimeCommand | TryLiquidProbeRunTimeCommand | AirGapInPlaceRunTimeCommand + | EvotipSealRunTimeCommand + | EvotipUnsealRunTimeCommand + | EvotipPressurizeRunTimeCommand export type PipettingCreateCommand = | AspirateCreateCommand @@ -41,6 +44,9 @@ export type PipettingCreateCommand = | LiquidProbeCreateCommand | TryLiquidProbeCreateCommand | AirGapInPlaceCreateCommand + | EvotipSealCreateCommand + | EvotipUnsealCreateCommand + | EvotipPressurizeCreateCommand export interface ConfigureForVolumeCreateCommand extends CommonCommandCreateInfo { @@ -237,6 +243,37 @@ export interface TryLiquidProbeRunTimeCommand result?: Record } +export interface EvotipSealCreateCommand extends CommonCommandCreateInfo { + commandType: 'evotipSealPipette' + params: PipetteAccessParams & WellLocationParam +} +export interface EvotipUnsealCreateCommand extends CommonCommandCreateInfo { + commandType: 'evotipUnsealPipette' + params: PipetteAccessParams & WellLocationParam +} + +export interface EvotipPressurizeCreateCommand extends CommonCommandCreateInfo { + commandType: 'evotipDispense' + params: PipetteAccessParams & + WellLocationParam & + FlowRateParams & + VolumeParams +} +export interface EvotipSealRunTimeCommand + extends CommonCommandRunTimeInfo, + EvotipSealCreateCommand { + result?: EvotipSealResult +} +export interface EvotipUnsealRunTimeCommand + extends CommonCommandRunTimeInfo, + EvotipUnsealCreateCommand { + result?: EvotipUnsealResult +} +export interface EvotipPressurizeRunTimeCommand + extends CommonCommandRunTimeInfo, + EvotipPressurizeCreateCommand { + result?: BasicLiquidHandlingResult +} export type AspDispAirgapParams = FlowRateParams & PipetteAccessParams & VolumeParams & @@ -321,3 +358,13 @@ interface TipPresenceResult { // ot2 should alwasy return unknown status?: 'present' | 'absent' | 'unknown' } + +interface EvotipSealResult { + position: AddressableOffsetVector + tipVolume: number + tipLength: number + tipDiameter: number +} +interface EvotipUnsealResult { + position: AddressableOffsetVector +} diff --git a/shared-data/deck/definitions/5/ot3_standard.json b/shared-data/deck/definitions/5/ot3_standard.json index f317b596ad1..720eae1147c 100644 --- a/shared-data/deck/definitions/5/ot3_standard.json +++ b/shared-data/deck/definitions/5/ot3_standard.json @@ -149,6 +149,7 @@ "id": "A3", "areaType": "slot", "offsetFromCutoutFixture": [0.0, 0.0, 0.0], + "matingSurfaceUnitVector": [-1, 1, -1], "boundingBox": { "xDimension": 128.0, "yDimension": 86.0, diff --git a/shared-data/js/__tests__/labwareDefQuirks.test.ts b/shared-data/js/__tests__/labwareDefQuirks.test.ts index 6251c894647..4ef69b5cb51 100644 --- a/shared-data/js/__tests__/labwareDefQuirks.test.ts +++ b/shared-data/js/__tests__/labwareDefQuirks.test.ts @@ -14,6 +14,7 @@ const EXPECTED_VALID_QUIRKS = [ 'gripperIncompatible', 'tiprackAdapterFor96Channel', 'stackingMaxFive', + 'stackingOnly', ] describe('check quirks for all labware defs', () => { diff --git a/shared-data/js/fixtures.ts b/shared-data/js/fixtures.ts index 76cc4c06fae..44d5c858788 100644 --- a/shared-data/js/fixtures.ts +++ b/shared-data/js/fixtures.ts @@ -120,6 +120,7 @@ export const FLEX_SINGLE_SLOT_BY_CUTOUT_ID: { [CutoutId: string]: string } = { cutoutD3: 'D3', } +// TODO(jh 01-15-25): Instead of typing slotId as `string`, type it as `AddressableAreaName`. // returns the position associated with a slot id export function getPositionFromSlotId( slotId: string, diff --git a/shared-data/js/labware.ts b/shared-data/js/labware.ts index 20d41c3a697..9faa6ced497 100644 --- a/shared-data/js/labware.ts +++ b/shared-data/js/labware.ts @@ -121,6 +121,8 @@ import thermoscientificnunc96Wellplate2000UlV1Uncasted from '../labware/definiti import tipone96Tiprack200UlV1Uncasted from '../labware/definitions/2/tipone_96_tiprack_200ul/1.json' import usascientific12Reservoir22MlV1Uncasted from '../labware/definitions/2/usascientific_12_reservoir_22ml/1.json' import usascientific96Wellplate24MlDeepV1Uncasted from '../labware/definitions/2/usascientific_96_wellplate_2.4ml_deep/1.json' +import evotipsFlex96TiprackAdapterV1Uncasted from '../labware/definitions/3/evotips_flex_96_tiprack_adapter/1.json' +import evotipsOpentrons96LabwareV1Uncasted from '../labware/definitions/3/evotips_opentrons_96_labware/1.json' // v1 legacy labware definitions @@ -297,6 +299,8 @@ const thermoscientificnunc96Wellplate2000UlV1 = thermoscientificnunc96Wellplate2 const tipone96Tiprack200UlV1 = tipone96Tiprack200UlV1Uncasted as LabwareDefinition2 const usascientific12Reservoir22MlV1 = usascientific12Reservoir22MlV1Uncasted as LabwareDefinition2 const usascientific96Wellplate24MlDeepV1 = usascientific96Wellplate24MlDeepV1Uncasted as LabwareDefinition2 +const evotipsFlex96TiprackAdapterV1 = evotipsFlex96TiprackAdapterV1Uncasted as LabwareDefinition2 +const evotipsOpentrons96LabwareV1 = evotipsOpentrons96LabwareV1Uncasted as LabwareDefinition2 // cast v1 defs @@ -466,6 +470,8 @@ const latestDefs = { tipone96Tiprack200UlV1, usascientific12Reservoir22MlV1, usascientific96Wellplate24MlDeepV1, + evotipsFlex96TiprackAdapterV1, + evotipsOpentrons96LabwareV1, } // labware definitions const getAllLabwareDefs = (): Record< diff --git a/shared-data/js/pipettes.ts b/shared-data/js/pipettes.ts index 134f4efbd82..5b390617f43 100644 --- a/shared-data/js/pipettes.ts +++ b/shared-data/js/pipettes.ts @@ -161,6 +161,7 @@ const getHighestVersion = ( path: string, pipetteModel: string, channels: Channels | null, + oemString: string, majorVersion: number, highestVersion: string ): string => { @@ -174,10 +175,10 @@ const getHighestVersion = ( // and make sure the given model, channels, and major/minor versions // are found in the path if ( - minorPathVersion > minorHighestVersion && + minorPathVersion >= minorHighestVersion && path.includes(`${majorPathVersion}_${minorPathVersion}`) && path.includes(pipetteModel) && - path.includes(channels ?? '') + path.includes(channels != null ? `${channels}${oemString}` : '') ) { highestVersion = `${majorPathVersion}_${minorPathVersion}` } @@ -239,6 +240,7 @@ export const getPipetteSpecsV2 = ( path, pipetteModel, channels, + oemString, majorVersion, highestVersion ) diff --git a/shared-data/labware/definitions/2/nest_96_wellplate_2ml_deep/2.json b/shared-data/labware/definitions/2/nest_96_wellplate_2ml_deep/2.json index 775596e7386..ad48d50fecc 100644 --- a/shared-data/labware/definitions/2/nest_96_wellplate_2ml_deep/2.json +++ b/shared-data/labware/definitions/2/nest_96_wellplate_2ml_deep/2.json @@ -1130,6 +1130,11 @@ "x": 0, "y": 0, "z": 16.1 + }, + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 102 } }, "stackingOffsetWithModule": { diff --git a/shared-data/labware/definitions/3/evotips_flex_96_tiprack_adapter/1.json b/shared-data/labware/definitions/3/evotips_flex_96_tiprack_adapter/1.json new file mode 100644 index 00000000000..36125856ad3 --- /dev/null +++ b/shared-data/labware/definitions/3/evotips_flex_96_tiprack_adapter/1.json @@ -0,0 +1,41 @@ +{ + "ordering": [], + "brand": { + "brand": "Opentrons", + "brandId": [] + }, + "metadata": { + "displayName": "Evotips adapter", + "displayCategory": "adapter", + "displayVolumeUnits": "\u00b5L", + "tags": [] + }, + "dimensions": { + "xDimension": 156.5, + "yDimension": 105, + "zDimension": 132 + }, + "wells": {}, + "groups": [ + { + "metadata": {}, + "wells": [] + } + ], + "parameters": { + "format": "96Standard", + "quirks": ["tiprackAdapterFor96Channel", "stackingMaxFive"], + "isTiprack": false, + "isMagneticModuleCompatible": false, + "loadName": "evotips_flex_96_tiprack_adapter" + }, + "namespace": "opentrons", + "version": 1, + "schemaVersion": 3, + "allowedRoles": ["adapter"], + "cornerOffsetFromSlot": { + "x": -14.25, + "y": -3.5, + "z": 0 + } +} diff --git a/shared-data/labware/definitions/3/evotips_opentrons_96_labware/1.json b/shared-data/labware/definitions/3/evotips_opentrons_96_labware/1.json new file mode 100644 index 00000000000..d2ecbdce217 --- /dev/null +++ b/shared-data/labware/definitions/3/evotips_opentrons_96_labware/1.json @@ -0,0 +1,1059 @@ +{ + "ordering": [ + ["A1", "B1", "C1", "D1", "E1", "F1", "G1", "H1"], + ["A2", "B2", "C2", "D2", "E2", "F2", "G2", "H2"], + ["A3", "B3", "C3", "D3", "E3", "F3", "G3", "H3"], + ["A4", "B4", "C4", "D4", "E4", "F4", "G4", "H4"], + ["A5", "B5", "C5", "D5", "E5", "F5", "G5", "H5"], + ["A6", "B6", "C6", "D6", "E6", "F6", "G6", "H6"], + ["A7", "B7", "C7", "D7", "E7", "F7", "G7", "H7"], + ["A8", "B8", "C8", "D8", "E8", "F8", "G8", "H8"], + ["A9", "B9", "C9", "D9", "E9", "F9", "G9", "H9"], + ["A10", "B10", "C10", "D10", "E10", "F10", "G10", "H10"], + ["A11", "B11", "C11", "D11", "E11", "F11", "G11", "H11"], + ["A12", "B12", "C12", "D12", "E12", "F12", "G12", "H12"] + ], + "brand": { + "brand": "opentrons", + "brandId": [] + }, + "metadata": { + "displayName": "Evotips", + "displayCategory": "wellPlate", + "displayVolumeUnits": "µL", + "tags": [] + }, + "dimensions": { + "xDimension": 127.75, + "yDimension": 86, + "zDimension": 39.25 + }, + "wells": { + "A1": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 14.08, + "y": 75.25, + "z": 1 + }, + "B1": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 14.08, + "y": 66.25, + "z": 1 + }, + "C1": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 14.08, + "y": 57.25, + "z": 1 + }, + "D1": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 14.08, + "y": 48.25, + "z": 1 + }, + "E1": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 14.08, + "y": 39.25, + "z": 1 + }, + "F1": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 14.08, + "y": 30.25, + "z": 1 + }, + "G1": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 14.08, + "y": 21.25, + "z": 1 + }, + "H1": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 14.08, + "y": 12.25, + "z": 1 + }, + "A2": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 23.08, + "y": 75.25, + "z": 1 + }, + "B2": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 23.08, + "y": 66.25, + "z": 1 + }, + "C2": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 23.08, + "y": 57.25, + "z": 1 + }, + "D2": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 23.08, + "y": 48.25, + "z": 1 + }, + "E2": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 23.08, + "y": 39.25, + "z": 1 + }, + "F2": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 23.08, + "y": 30.25, + "z": 1 + }, + "G2": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 23.08, + "y": 21.25, + "z": 1 + }, + "H2": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 23.08, + "y": 12.25, + "z": 1 + }, + "A3": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 32.08, + "y": 75.25, + "z": 1 + }, + "B3": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 32.08, + "y": 66.25, + "z": 1 + }, + "C3": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 32.08, + "y": 57.25, + "z": 1 + }, + "D3": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 32.08, + "y": 48.25, + "z": 1 + }, + "E3": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 32.08, + "y": 39.25, + "z": 1 + }, + "F3": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 32.08, + "y": 30.25, + "z": 1 + }, + "G3": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 32.08, + "y": 21.25, + "z": 1 + }, + "H3": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 32.08, + "y": 12.25, + "z": 1 + }, + "A4": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 41.08, + "y": 75.25, + "z": 1 + }, + "B4": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 41.08, + "y": 66.25, + "z": 1 + }, + "C4": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 41.08, + "y": 57.25, + "z": 1 + }, + "D4": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 41.08, + "y": 48.25, + "z": 1 + }, + "E4": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 41.08, + "y": 39.25, + "z": 1 + }, + "F4": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 41.08, + "y": 30.25, + "z": 1 + }, + "G4": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 41.08, + "y": 21.25, + "z": 1 + }, + "H4": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 41.08, + "y": 12.25, + "z": 1 + }, + "A5": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 50.08, + "y": 75.25, + "z": 1 + }, + "B5": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 50.08, + "y": 66.25, + "z": 1 + }, + "C5": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 50.08, + "y": 57.25, + "z": 1 + }, + "D5": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 50.08, + "y": 48.25, + "z": 1 + }, + "E5": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 50.08, + "y": 39.25, + "z": 1 + }, + "F5": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 50.08, + "y": 30.25, + "z": 1 + }, + "G5": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 50.08, + "y": 21.25, + "z": 1 + }, + "H5": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 50.08, + "y": 12.25, + "z": 1 + }, + "A6": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 59.08, + "y": 75.25, + "z": 1 + }, + "B6": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 59.08, + "y": 66.25, + "z": 1 + }, + "C6": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 59.08, + "y": 57.25, + "z": 1 + }, + "D6": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 59.08, + "y": 48.25, + "z": 1 + }, + "E6": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 59.08, + "y": 39.25, + "z": 1 + }, + "F6": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 59.08, + "y": 30.25, + "z": 1 + }, + "G6": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 59.08, + "y": 21.25, + "z": 1 + }, + "H6": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 59.08, + "y": 12.25, + "z": 1 + }, + "A7": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 68.08, + "y": 75.25, + "z": 1 + }, + "B7": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 68.08, + "y": 66.25, + "z": 1 + }, + "C7": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 68.08, + "y": 57.25, + "z": 1 + }, + "D7": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 68.08, + "y": 48.25, + "z": 1 + }, + "E7": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 68.08, + "y": 39.25, + "z": 1 + }, + "F7": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 68.08, + "y": 30.25, + "z": 1 + }, + "G7": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 68.08, + "y": 21.25, + "z": 1 + }, + "H7": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 68.08, + "y": 12.25, + "z": 1 + }, + "A8": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 77.08, + "y": 75.25, + "z": 1 + }, + "B8": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 77.08, + "y": 66.25, + "z": 1 + }, + "C8": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 77.08, + "y": 57.25, + "z": 1 + }, + "D8": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 77.08, + "y": 48.25, + "z": 1 + }, + "E8": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 77.08, + "y": 39.25, + "z": 1 + }, + "F8": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 77.08, + "y": 30.25, + "z": 1 + }, + "G8": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 77.08, + "y": 21.25, + "z": 1 + }, + "H8": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 77.08, + "y": 12.25, + "z": 1 + }, + "A9": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 86.08, + "y": 75.25, + "z": 1 + }, + "B9": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 86.08, + "y": 66.25, + "z": 1 + }, + "C9": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 86.08, + "y": 57.25, + "z": 1 + }, + "D9": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 86.08, + "y": 48.25, + "z": 1 + }, + "E9": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 86.08, + "y": 39.25, + "z": 1 + }, + "F9": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 86.08, + "y": 30.25, + "z": 1 + }, + "G9": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 86.08, + "y": 21.25, + "z": 1 + }, + "H9": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 86.08, + "y": 12.25, + "z": 1 + }, + "A10": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 95.08, + "y": 75.25, + "z": 1 + }, + "B10": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 95.08, + "y": 66.25, + "z": 1 + }, + "C10": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 95.08, + "y": 57.25, + "z": 1 + }, + "D10": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 95.08, + "y": 48.25, + "z": 1 + }, + "E10": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 95.08, + "y": 39.25, + "z": 1 + }, + "F10": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 95.08, + "y": 30.25, + "z": 1 + }, + "G10": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 95.08, + "y": 21.25, + "z": 1 + }, + "H10": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 95.08, + "y": 12.25, + "z": 1 + }, + "A11": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 104.08, + "y": 75.25, + "z": 1 + }, + "B11": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 104.08, + "y": 66.25, + "z": 1 + }, + "C11": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 104.08, + "y": 57.25, + "z": 1 + }, + "D11": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 104.08, + "y": 48.25, + "z": 1 + }, + "E11": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 104.08, + "y": 39.25, + "z": 1 + }, + "F11": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 104.08, + "y": 30.25, + "z": 1 + }, + "G11": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 104.08, + "y": 21.25, + "z": 1 + }, + "H11": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 104.08, + "y": 12.25, + "z": 1 + }, + "A12": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 113.08, + "y": 75.25, + "z": 1 + }, + "B12": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 113.08, + "y": 66.25, + "z": 1 + }, + "C12": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 113.08, + "y": 57.25, + "z": 1 + }, + "D12": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 113.08, + "y": 48.25, + "z": 1 + }, + "E12": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 113.08, + "y": 39.25, + "z": 1 + }, + "F12": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 113.08, + "y": 30.25, + "z": 1 + }, + "G12": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 113.08, + "y": 21.25, + "z": 1 + }, + "H12": { + "depth": 54, + "totalLiquidVolume": 1000, + "shape": "circular", + "diameter": 7, + "x": 113.08, + "y": 12.25, + "z": 1 + } + }, + "groups": [ + { + "metadata": { + "wellBottomShape": "v" + }, + "wells": [ + "A1", + "B1", + "C1", + "D1", + "E1", + "F1", + "G1", + "H1", + "A2", + "B2", + "C2", + "D2", + "E2", + "F2", + "G2", + "H2", + "A3", + "B3", + "C3", + "D3", + "E3", + "F3", + "G3", + "H3", + "A4", + "B4", + "C4", + "D4", + "E4", + "F4", + "G4", + "H4", + "A5", + "B5", + "C5", + "D5", + "E5", + "F5", + "G5", + "H5", + "A6", + "B6", + "C6", + "D6", + "E6", + "F6", + "G6", + "H6", + "A7", + "B7", + "C7", + "D7", + "E7", + "F7", + "G7", + "H7", + "A8", + "B8", + "C8", + "D8", + "E8", + "F8", + "G8", + "H8", + "A9", + "B9", + "C9", + "D9", + "E9", + "F9", + "G9", + "H9", + "A10", + "B10", + "C10", + "D10", + "E10", + "F10", + "G10", + "H10", + "A11", + "B11", + "C11", + "D11", + "E11", + "F11", + "G11", + "H11", + "A12", + "B12", + "C12", + "D12", + "E12", + "F12", + "G12", + "H12" + ] + } + ], + "parameters": { + "format": "96Standard", + "quirks": ["stackingOnly"], + "isTiprack": false, + "tipLength": 42.0, + "tipOverlap": 10.0, + "isMagneticModuleCompatible": false, + "loadName": "evotips_opentrons_96_labware" + }, + "namespace": "opentrons", + "allowedRoles": ["labware"], + "version": 1, + "stackLimit": 5, + "compatibleParentLabware": [ + "nest_96_wellplate_2ml_deep", + "nest_1_reservoir_195ml", + "evotips_flex_96_tiprack_adapter" + ], + "schemaVersion": 3, + "cornerOffsetFromSlot": { + "x": 0, + "y": 0, + "z": 0 + }, + "gripHeightFromLabwareBottom": 14.5, + "gripForce": 15, + "gripperOffsets": { + "default": { + "pickUpOffset": { + "x": 0, + "y": 0, + "z": 15 + }, + "dropOffset": { + "x": 0, + "y": 0, + "z": 15 + } + } + }, + "stackingOffsetWithLabware": { + "nest_96_wellplate_2ml_deep": { + "x": 0, + "y": 0, + "z": 22.5 + }, + "nest_1_reservoir_195ml": { + "x": 0, + "y": 0, + "z": 22.5 + }, + "evotips_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 76.78 + } + } +} diff --git a/shared-data/python/opentrons_shared_data/errors/exceptions.py b/shared-data/python/opentrons_shared_data/errors/exceptions.py index b27b3c9c3d3..bdc952d5760 100644 --- a/shared-data/python/opentrons_shared_data/errors/exceptions.py +++ b/shared-data/python/opentrons_shared_data/errors/exceptions.py @@ -1,4 +1,5 @@ """Exception hierarchy for error codes.""" + from typing import Dict, Any, Optional, List, Iterator, Union, Sequence, overload from logging import getLogger from traceback import format_exception_only, format_tb @@ -1099,7 +1100,7 @@ def __init__( self, message: Optional[str] = None, detail: Optional[Dict[str, str]] = None, - wrapping: Optional[Sequence[EnumeratedError]] = None, + wrapping: Optional[Sequence[Union[EnumeratedError, BaseException]]] = None, ) -> None: """Build an InvalidProtocolData.""" super().__init__(ErrorCodes.INVALID_PROTOCOL_DATA, message, detail, wrapping)