From 76008349455561130c2a5b6c8ca9f1fe80c221fc Mon Sep 17 00:00:00 2001 From: Shlok Amin <shlokamin@me.com> Date: Fri, 8 Apr 2022 17:41:44 -0400 Subject: [PATCH 1/6] feat(protocol-designer): add load liquid commands #9702 --- .../fixtures/protocol/5/multipleLiquids.json | 2695 +++++++++++++++++ .../src/load-file/migration/6_0_0.ts | 91 +- .../migration/__tests__/6_0_0.test.ts | 191 ++ .../protocol/types/schemaV6/command/gantry.ts | 26 +- .../protocol/types/schemaV6/command/index.ts | 2 +- .../protocol/types/schemaV6/command/module.ts | 90 +- .../types/schemaV6/command/pipetting.ts | 43 +- .../protocol/types/schemaV6/command/setup.ts | 19 +- .../protocol/types/schemaV6/command/timing.ts | 10 +- 9 files changed, 3049 insertions(+), 118 deletions(-) create mode 100644 protocol-designer/fixtures/protocol/5/multipleLiquids.json diff --git a/protocol-designer/fixtures/protocol/5/multipleLiquids.json b/protocol-designer/fixtures/protocol/5/multipleLiquids.json new file mode 100644 index 00000000000..1772977b187 --- /dev/null +++ b/protocol-designer/fixtures/protocol/5/multipleLiquids.json @@ -0,0 +1,2695 @@ +{ + "metadata": { + "protocolName": "test liquids", + "author": "", + "description": "", + "created": 1649435471567, + "lastModified": 1649435581085, + "category": null, + "subcategory": null, + "tags": [] + }, + "designerApplication": { + "name": "opentrons/protocol-designer", + "version": "5.2.6", + "data": { + "_internalAppBuildDate": "Mon, 26 Apr 2021 18:42:28 GMT", + "defaultValues": { + "aspirate_mmFromBottom": 1, + "dispense_mmFromBottom": 0.5, + "touchTip_mmFromTop": -1, + "blowout_mmFromTop": 0 + }, + "pipetteTiprackAssignments": { + "4d23ffe0-b759-11ec-81e8-7fa12dc3e861": "opentrons/opentrons_96_filtertiprack_20ul/1" + }, + "dismissedWarnings": { "form": {}, "timeline": {} }, + "ingredients": { + "0": { + "name": "water", + "description": "water", + "serialize": false, + "liquidGroupId": "0" + }, + "1": { + "name": "plasma", + "description": "plasma", + "serialize": false, + "liquidGroupId": "1" + }, + "2": { + "name": "vinegar", + "description": "vinegar", + "serialize": false, + "liquidGroupId": "2" + } + }, + "ingredLocations": { + "6114d3d0-b759-11ec-81e8-7fa12dc3e861:opentrons/opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap/1": { + "A1": { "0": { "volume": 222 } }, + "B1": { "0": { "volume": 222 } }, + "C1": { "0": { "volume": 222 } }, + "D1": { "0": { "volume": 222 } }, + "A2": { "0": { "volume": 222 } }, + "B2": { "0": { "volume": 222 } }, + "C2": { "0": { "volume": 222 } }, + "D2": { "0": { "volume": 222 } }, + "A3": { "1": { "volume": 333 } }, + "B3": { "1": { "volume": 333 } }, + "C3": { "1": { "volume": 333 } }, + "D3": { "1": { "volume": 333 } }, + "A4": { "1": { "volume": 333 } }, + "B4": { "1": { "volume": 333 } }, + "C4": { "1": { "volume": 333 } }, + "D4": { "1": { "volume": 333 } }, + "A5": { "2": { "volume": 444 } }, + "B5": { "2": { "volume": 444 } }, + "C5": { "2": { "volume": 444 } }, + "D5": { "2": { "volume": 444 } }, + "A6": { "2": { "volume": 444 } }, + "B6": { "2": { "volume": 444 } }, + "C6": { "2": { "volume": 444 } }, + "D6": { "2": { "volume": 444 } } + }, + "64c66a20-b759-11ec-81e8-7fa12dc3e861:opentrons/usascientific_96_wellplate_2.4ml_deep/1": { + "A1": { "0": { "volume": 555 } }, + "B1": { "0": { "volume": 555 } }, + "C1": { "0": { "volume": 555 } }, + "D1": { "0": { "volume": 555 } }, + "E1": { "0": { "volume": 555 } }, + "F1": { "0": { "volume": 555 } }, + "G1": { "0": { "volume": 555 } }, + "H1": { "0": { "volume": 555 } }, + "A2": { "0": { "volume": 555 } }, + "B2": { "0": { "volume": 555 } }, + "C2": { "0": { "volume": 555 } }, + "D2": { "0": { "volume": 555 } }, + "E2": { "0": { "volume": 555 } }, + "F2": { "0": { "volume": 555 } }, + "G2": { "0": { "volume": 555 } }, + "H2": { "0": { "volume": 555 } }, + "A3": { "0": { "volume": 555 } }, + "B3": { "0": { "volume": 555 } }, + "C3": { "0": { "volume": 555 } }, + "D3": { "0": { "volume": 555 } }, + "E3": { "0": { "volume": 555 } }, + "F3": { "0": { "volume": 555 } }, + "G3": { "0": { "volume": 555 } }, + "H3": { "0": { "volume": 555 } }, + "A4": { "1": { "volume": 666 } }, + "B4": { "1": { "volume": 666 } }, + "C4": { "1": { "volume": 666 } }, + "D4": { "1": { "volume": 666 } }, + "E4": { "1": { "volume": 666 } }, + "F4": { "1": { "volume": 666 } }, + "G4": { "1": { "volume": 666 } }, + "H4": { "1": { "volume": 666 } }, + "A5": { "1": { "volume": 666 } }, + "B5": { "1": { "volume": 666 } }, + "C5": { "1": { "volume": 666 } }, + "D5": { "1": { "volume": 666 } }, + "E5": { "1": { "volume": 666 } }, + "F5": { "1": { "volume": 666 } }, + "G5": { "1": { "volume": 666 } }, + "H5": { "1": { "volume": 666 } }, + "A6": { "1": { "volume": 666 } }, + "B6": { "1": { "volume": 666 } }, + "C6": { "1": { "volume": 666 } }, + "D6": { "1": { "volume": 666 } }, + "E6": { "1": { "volume": 666 } }, + "F6": { "1": { "volume": 666 } }, + "G6": { "1": { "volume": 666 } }, + "H6": { "1": { "volume": 666 } }, + "A7": { "2": { "volume": 777 } }, + "B7": { "2": { "volume": 777 } }, + "C7": { "2": { "volume": 777 } }, + "D7": { "2": { "volume": 777 } }, + "E7": { "2": { "volume": 777 } }, + "F7": { "2": { "volume": 777 } }, + "G7": { "2": { "volume": 777 } }, + "H7": { "2": { "volume": 777 } }, + "A8": { "2": { "volume": 777 } }, + "B8": { "2": { "volume": 777 } }, + "C8": { "2": { "volume": 777 } }, + "D8": { "2": { "volume": 777 } }, + "E8": { "2": { "volume": 777 } }, + "F8": { "2": { "volume": 777 } }, + "G8": { "2": { "volume": 777 } }, + "H8": { "2": { "volume": 777 } }, + "A9": { "2": { "volume": 777 } }, + "B9": { "2": { "volume": 777 } }, + "C9": { "2": { "volume": 777 } }, + "D9": { "2": { "volume": 777 } }, + "E9": { "2": { "volume": 777 } }, + "F9": { "2": { "volume": 777 } }, + "G9": { "2": { "volume": 777 } }, + "H9": { "2": { "volume": 777 } }, + "A10": { "2": { "volume": 777 } }, + "B10": { "2": { "volume": 777 } }, + "C10": { "2": { "volume": 777 } }, + "D10": { "2": { "volume": 777 } }, + "E10": { "2": { "volume": 777 } }, + "F10": { "2": { "volume": 777 } }, + "G10": { "2": { "volume": 777 } }, + "H10": { "2": { "volume": 777 } }, + "A11": { "2": { "volume": 777 } }, + "B11": { "2": { "volume": 777 } }, + "C11": { "2": { "volume": 777 } }, + "D11": { "2": { "volume": 777 } }, + "E11": { "2": { "volume": 777 } }, + "F11": { "2": { "volume": 777 } }, + "G11": { "2": { "volume": 777 } }, + "H11": { "2": { "volume": 777 } }, + "A12": { "2": { "volume": 777 } }, + "B12": { "2": { "volume": 777 } }, + "C12": { "2": { "volume": 777 } }, + "D12": { "2": { "volume": 777 } }, + "E12": { "2": { "volume": 777 } }, + "F12": { "2": { "volume": 777 } }, + "G12": { "2": { "volume": 777 } }, + "H12": { "2": { "volume": 777 } } + } + }, + "savedStepForms": { + "__INITIAL_DECK_SETUP_STEP__": { + "stepType": "manualIntervention", + "id": "__INITIAL_DECK_SETUP_STEP__", + "labwareLocationUpdate": { + "trashId": "12", + "4d253860-b759-11ec-81e8-7fa12dc3e861:opentrons/opentrons_96_filtertiprack_20ul/1": "1", + "6114d3d0-b759-11ec-81e8-7fa12dc3e861:opentrons/opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap/1": "10", + "64c66a20-b759-11ec-81e8-7fa12dc3e861:opentrons/usascientific_96_wellplate_2.4ml_deep/1": "8" + }, + "pipetteLocationUpdate": { + "4d23ffe0-b759-11ec-81e8-7fa12dc3e861": "left" + }, + "moduleLocationUpdate": {} + } + }, + "orderedStepIds": [] + } + }, + "robot": { "model": "OT-2 Standard" }, + "pipettes": { + "4d23ffe0-b759-11ec-81e8-7fa12dc3e861": { + "mount": "left", + "name": "p300_single_gen2" + } + }, + "labware": { + "trashId": { + "slot": "12", + "displayName": "Trash", + "definitionId": "opentrons/opentrons_1_trash_1100ml_fixed/1" + }, + "4d253860-b759-11ec-81e8-7fa12dc3e861:opentrons/opentrons_96_filtertiprack_20ul/1": { + "slot": "1", + "displayName": "Opentrons 96 Filter Tip Rack 20 µL", + "definitionId": "opentrons/opentrons_96_filtertiprack_20ul/1" + }, + "6114d3d0-b759-11ec-81e8-7fa12dc3e861:opentrons/opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap/1": { + "slot": "10", + "displayName": "Opentrons 24 Tube Rack with Eppendorf 1.5 mL Safe-Lock Snapcap", + "definitionId": "opentrons/opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap/1" + }, + "64c66a20-b759-11ec-81e8-7fa12dc3e861:opentrons/usascientific_96_wellplate_2.4ml_deep/1": { + "slot": "8", + "displayName": "USA Scientific 96 Deep Well Plate 2.4 mL", + "definitionId": "opentrons/usascientific_96_wellplate_2.4ml_deep/1" + } + }, + "labwareDefinitions": { + "opentrons/opentrons_96_filtertiprack_20ul/1": { + "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": [], "links": [] }, + "metadata": { + "displayName": "Opentrons 96 Filter Tip Rack 20 µL", + "displayCategory": "tipRack", + "displayVolumeUnits": "µL", + "tags": [] + }, + "dimensions": { + "xDimension": 127.76, + "yDimension": 85.48, + "zDimension": 64.69 + }, + "wells": { + "A1": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 14.36, + "y": 74.26, + "z": 25.49 + }, + "B1": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 14.36, + "y": 65.26, + "z": 25.49 + }, + "C1": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 14.36, + "y": 56.26, + "z": 25.49 + }, + "D1": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 14.36, + "y": 47.26, + "z": 25.49 + }, + "E1": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 14.36, + "y": 38.26, + "z": 25.49 + }, + "F1": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 14.36, + "y": 29.26, + "z": 25.49 + }, + "G1": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 14.36, + "y": 20.26, + "z": 25.49 + }, + "H1": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 14.36, + "y": 11.26, + "z": 25.49 + }, + "A2": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 23.36, + "y": 74.26, + "z": 25.49 + }, + "B2": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 23.36, + "y": 65.26, + "z": 25.49 + }, + "C2": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 23.36, + "y": 56.26, + "z": 25.49 + }, + "D2": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 23.36, + "y": 47.26, + "z": 25.49 + }, + "E2": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 23.36, + "y": 38.26, + "z": 25.49 + }, + "F2": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 23.36, + "y": 29.26, + "z": 25.49 + }, + "G2": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 23.36, + "y": 20.26, + "z": 25.49 + }, + "H2": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 23.36, + "y": 11.26, + "z": 25.49 + }, + "A3": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 32.36, + "y": 74.26, + "z": 25.49 + }, + "B3": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 32.36, + "y": 65.26, + "z": 25.49 + }, + "C3": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 32.36, + "y": 56.26, + "z": 25.49 + }, + "D3": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 32.36, + "y": 47.26, + "z": 25.49 + }, + "E3": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 32.36, + "y": 38.26, + "z": 25.49 + }, + "F3": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 32.36, + "y": 29.26, + "z": 25.49 + }, + "G3": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 32.36, + "y": 20.26, + "z": 25.49 + }, + "H3": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 32.36, + "y": 11.26, + "z": 25.49 + }, + "A4": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 41.36, + "y": 74.26, + "z": 25.49 + }, + "B4": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 41.36, + "y": 65.26, + "z": 25.49 + }, + "C4": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 41.36, + "y": 56.26, + "z": 25.49 + }, + "D4": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 41.36, + "y": 47.26, + "z": 25.49 + }, + "E4": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 41.36, + "y": 38.26, + "z": 25.49 + }, + "F4": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 41.36, + "y": 29.26, + "z": 25.49 + }, + "G4": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 41.36, + "y": 20.26, + "z": 25.49 + }, + "H4": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 41.36, + "y": 11.26, + "z": 25.49 + }, + "A5": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 50.36, + "y": 74.26, + "z": 25.49 + }, + "B5": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 50.36, + "y": 65.26, + "z": 25.49 + }, + "C5": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 50.36, + "y": 56.26, + "z": 25.49 + }, + "D5": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 50.36, + "y": 47.26, + "z": 25.49 + }, + "E5": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 50.36, + "y": 38.26, + "z": 25.49 + }, + "F5": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 50.36, + "y": 29.26, + "z": 25.49 + }, + "G5": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 50.36, + "y": 20.26, + "z": 25.49 + }, + "H5": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 50.36, + "y": 11.26, + "z": 25.49 + }, + "A6": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 59.36, + "y": 74.26, + "z": 25.49 + }, + "B6": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 59.36, + "y": 65.26, + "z": 25.49 + }, + "C6": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 59.36, + "y": 56.26, + "z": 25.49 + }, + "D6": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 59.36, + "y": 47.26, + "z": 25.49 + }, + "E6": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 59.36, + "y": 38.26, + "z": 25.49 + }, + "F6": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 59.36, + "y": 29.26, + "z": 25.49 + }, + "G6": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 59.36, + "y": 20.26, + "z": 25.49 + }, + "H6": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 59.36, + "y": 11.26, + "z": 25.49 + }, + "A7": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 68.36, + "y": 74.26, + "z": 25.49 + }, + "B7": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 68.36, + "y": 65.26, + "z": 25.49 + }, + "C7": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 68.36, + "y": 56.26, + "z": 25.49 + }, + "D7": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 68.36, + "y": 47.26, + "z": 25.49 + }, + "E7": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 68.36, + "y": 38.26, + "z": 25.49 + }, + "F7": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 68.36, + "y": 29.26, + "z": 25.49 + }, + "G7": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 68.36, + "y": 20.26, + "z": 25.49 + }, + "H7": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 68.36, + "y": 11.26, + "z": 25.49 + }, + "A8": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 77.36, + "y": 74.26, + "z": 25.49 + }, + "B8": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 77.36, + "y": 65.26, + "z": 25.49 + }, + "C8": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 77.36, + "y": 56.26, + "z": 25.49 + }, + "D8": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 77.36, + "y": 47.26, + "z": 25.49 + }, + "E8": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 77.36, + "y": 38.26, + "z": 25.49 + }, + "F8": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 77.36, + "y": 29.26, + "z": 25.49 + }, + "G8": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 77.36, + "y": 20.26, + "z": 25.49 + }, + "H8": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 77.36, + "y": 11.26, + "z": 25.49 + }, + "A9": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 86.36, + "y": 74.26, + "z": 25.49 + }, + "B9": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 86.36, + "y": 65.26, + "z": 25.49 + }, + "C9": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 86.36, + "y": 56.26, + "z": 25.49 + }, + "D9": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 86.36, + "y": 47.26, + "z": 25.49 + }, + "E9": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 86.36, + "y": 38.26, + "z": 25.49 + }, + "F9": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 86.36, + "y": 29.26, + "z": 25.49 + }, + "G9": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 86.36, + "y": 20.26, + "z": 25.49 + }, + "H9": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 86.36, + "y": 11.26, + "z": 25.49 + }, + "A10": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 95.36, + "y": 74.26, + "z": 25.49 + }, + "B10": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 95.36, + "y": 65.26, + "z": 25.49 + }, + "C10": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 95.36, + "y": 56.26, + "z": 25.49 + }, + "D10": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 95.36, + "y": 47.26, + "z": 25.49 + }, + "E10": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 95.36, + "y": 38.26, + "z": 25.49 + }, + "F10": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 95.36, + "y": 29.26, + "z": 25.49 + }, + "G10": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 95.36, + "y": 20.26, + "z": 25.49 + }, + "H10": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 95.36, + "y": 11.26, + "z": 25.49 + }, + "A11": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 104.36, + "y": 74.26, + "z": 25.49 + }, + "B11": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 104.36, + "y": 65.26, + "z": 25.49 + }, + "C11": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 104.36, + "y": 56.26, + "z": 25.49 + }, + "D11": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 104.36, + "y": 47.26, + "z": 25.49 + }, + "E11": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 104.36, + "y": 38.26, + "z": 25.49 + }, + "F11": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 104.36, + "y": 29.26, + "z": 25.49 + }, + "G11": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 104.36, + "y": 20.26, + "z": 25.49 + }, + "H11": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 104.36, + "y": 11.26, + "z": 25.49 + }, + "A12": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 113.36, + "y": 74.26, + "z": 25.49 + }, + "B12": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 113.36, + "y": 65.26, + "z": 25.49 + }, + "C12": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 113.36, + "y": 56.26, + "z": 25.49 + }, + "D12": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 113.36, + "y": 47.26, + "z": 25.49 + }, + "E12": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 113.36, + "y": 38.26, + "z": 25.49 + }, + "F12": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 113.36, + "y": 29.26, + "z": 25.49 + }, + "G12": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 113.36, + "y": 20.26, + "z": 25.49 + }, + "H12": { + "depth": 39.2, + "shape": "circular", + "diameter": 3.27, + "totalLiquidVolume": 20, + "x": 113.36, + "y": 11.26, + "z": 25.49 + } + }, + "groups": [ + { + "metadata": {}, + "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", + "isTiprack": true, + "tipLength": 39.2, + "tipOverlap": 3.29, + "isMagneticModuleCompatible": false, + "loadName": "opentrons_96_filtertiprack_20ul" + }, + "namespace": "opentrons", + "version": 1, + "schemaVersion": 2, + "cornerOffsetFromSlot": { "x": 0, "y": 0, "z": 0 } + }, + "opentrons/opentrons_1_trash_1100ml_fixed/1": { + "ordering": [["A1"]], + "metadata": { + "displayCategory": "trash", + "displayVolumeUnits": "mL", + "displayName": "Opentrons Fixed Trash", + "tags": [] + }, + "schemaVersion": 2, + "version": 1, + "namespace": "opentrons", + "dimensions": { + "xDimension": 172.86, + "yDimension": 165.86, + "zDimension": 82 + }, + "parameters": { + "format": "trash", + "isTiprack": false, + "loadName": "opentrons_1_trash_1100ml_fixed", + "isMagneticModuleCompatible": false, + "quirks": [ + "fixedTrash", + "centerMultichannelOnWells", + "touchTipDisabled" + ] + }, + "wells": { + "A1": { + "shape": "rectangular", + "yDimension": 165.67, + "xDimension": 107.11, + "totalLiquidVolume": 1100000, + "depth": 0, + "x": 82.84, + "y": 80, + "z": 82 + } + }, + "brand": { "brand": "Opentrons" }, + "groups": [{ "wells": ["A1"], "metadata": {} }], + "cornerOffsetFromSlot": { "x": 0, "y": 0, "z": 0 } + }, + "opentrons/opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap/1": { + "ordering": [ + ["A1", "B1", "C1", "D1"], + ["A2", "B2", "C2", "D2"], + ["A3", "B3", "C3", "D3"], + ["A4", "B4", "C4", "D4"], + ["A5", "B5", "C5", "D5"], + ["A6", "B6", "C6", "D6"] + ], + "schemaVersion": 2, + "version": 1, + "namespace": "opentrons", + "metadata": { + "tags": [], + "displayName": "Opentrons 24 Tube Rack with Eppendorf 1.5 mL Safe-Lock Snapcap", + "displayVolumeUnits": "mL", + "displayCategory": "tubeRack" + }, + "dimensions": { + "xDimension": 127.75, + "yDimension": 85.5, + "zDimension": 79.85 + }, + "parameters": { + "format": "irregular", + "isTiprack": false, + "isMagneticModuleCompatible": false, + "loadName": "opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap" + }, + "wells": { + "D1": { + "depth": 37.8, + "diameter": 8.7, + "shape": "circular", + "totalLiquidVolume": 1500, + "x": 18.21, + "y": 17.59, + "z": 42.05 + }, + "C1": { + "depth": 37.8, + "diameter": 8.7, + "shape": "circular", + "totalLiquidVolume": 1500, + "x": 18.21, + "y": 36.87, + "z": 42.05 + }, + "B1": { + "depth": 37.8, + "diameter": 8.7, + "shape": "circular", + "totalLiquidVolume": 1500, + "x": 18.21, + "y": 56.15, + "z": 42.05 + }, + "A1": { + "depth": 37.8, + "diameter": 8.7, + "shape": "circular", + "totalLiquidVolume": 1500, + "x": 18.21, + "y": 75.43, + "z": 42.05 + }, + "D2": { + "depth": 37.8, + "diameter": 8.7, + "shape": "circular", + "totalLiquidVolume": 1500, + "x": 38.1, + "y": 17.59, + "z": 42.05 + }, + "C2": { + "depth": 37.8, + "diameter": 8.7, + "shape": "circular", + "totalLiquidVolume": 1500, + "x": 38.1, + "y": 36.87, + "z": 42.05 + }, + "B2": { + "depth": 37.8, + "diameter": 8.7, + "shape": "circular", + "totalLiquidVolume": 1500, + "x": 38.1, + "y": 56.15, + "z": 42.05 + }, + "A2": { + "depth": 37.8, + "diameter": 8.7, + "shape": "circular", + "totalLiquidVolume": 1500, + "x": 38.1, + "y": 75.43, + "z": 42.05 + }, + "D3": { + "depth": 37.8, + "diameter": 8.7, + "shape": "circular", + "totalLiquidVolume": 1500, + "x": 57.99, + "y": 17.59, + "z": 42.05 + }, + "C3": { + "depth": 37.8, + "diameter": 8.7, + "shape": "circular", + "totalLiquidVolume": 1500, + "x": 57.99, + "y": 36.87, + "z": 42.05 + }, + "B3": { + "depth": 37.8, + "diameter": 8.7, + "shape": "circular", + "totalLiquidVolume": 1500, + "x": 57.99, + "y": 56.15, + "z": 42.05 + }, + "A3": { + "depth": 37.8, + "diameter": 8.7, + "shape": "circular", + "totalLiquidVolume": 1500, + "x": 57.99, + "y": 75.43, + "z": 42.05 + }, + "D4": { + "depth": 37.8, + "diameter": 8.7, + "shape": "circular", + "totalLiquidVolume": 1500, + "x": 77.88, + "y": 17.59, + "z": 42.05 + }, + "C4": { + "depth": 37.8, + "diameter": 8.7, + "shape": "circular", + "totalLiquidVolume": 1500, + "x": 77.88, + "y": 36.87, + "z": 42.05 + }, + "B4": { + "depth": 37.8, + "diameter": 8.7, + "shape": "circular", + "totalLiquidVolume": 1500, + "x": 77.88, + "y": 56.15, + "z": 42.05 + }, + "A4": { + "depth": 37.8, + "diameter": 8.7, + "shape": "circular", + "totalLiquidVolume": 1500, + "x": 77.88, + "y": 75.43, + "z": 42.05 + }, + "D5": { + "depth": 37.8, + "diameter": 8.7, + "shape": "circular", + "totalLiquidVolume": 1500, + "x": 97.77, + "y": 17.59, + "z": 42.05 + }, + "C5": { + "depth": 37.8, + "diameter": 8.7, + "shape": "circular", + "totalLiquidVolume": 1500, + "x": 97.77, + "y": 36.87, + "z": 42.05 + }, + "B5": { + "depth": 37.8, + "diameter": 8.7, + "shape": "circular", + "totalLiquidVolume": 1500, + "x": 97.77, + "y": 56.15, + "z": 42.05 + }, + "A5": { + "depth": 37.8, + "diameter": 8.7, + "shape": "circular", + "totalLiquidVolume": 1500, + "x": 97.77, + "y": 75.43, + "z": 42.05 + }, + "D6": { + "depth": 37.8, + "diameter": 8.7, + "shape": "circular", + "totalLiquidVolume": 1500, + "x": 117.66, + "y": 17.59, + "z": 42.05 + }, + "C6": { + "depth": 37.8, + "diameter": 8.7, + "shape": "circular", + "totalLiquidVolume": 1500, + "x": 117.66, + "y": 36.87, + "z": 42.05 + }, + "B6": { + "depth": 37.8, + "diameter": 8.7, + "shape": "circular", + "totalLiquidVolume": 1500, + "x": 117.66, + "y": 56.15, + "z": 42.05 + }, + "A6": { + "depth": 37.8, + "diameter": 8.7, + "shape": "circular", + "totalLiquidVolume": 1500, + "x": 117.66, + "y": 75.43, + "z": 42.05 + } + }, + "brand": { + "brand": "Opentrons", + "brandId": [], + "links": [ + "https://shop.opentrons.com/collections/opentrons-tips/products/tube-rack-set-1" + ] + }, + "groups": [ + { + "wells": [ + "A1", + "B1", + "C1", + "D1", + "A2", + "B2", + "C2", + "D2", + "A3", + "B3", + "C3", + "D3", + "A4", + "B4", + "C4", + "D4", + "A5", + "B5", + "C5", + "D5", + "A6", + "B6", + "C6", + "D6" + ], + "metadata": { + "displayName": "Eppendorf 24x1.5 mL Safelock Snapcap", + "displayCategory": "tubeRack", + "wellBottomShape": "v" + }, + "brand": { + "brand": "Eppendorf", + "brandId": [ + "022363204", + "022363212", + "022363221", + "022363247", + "022363263", + "022363280", + "022363280", + "022363301", + "022363328" + ], + "links": [ + "https://online-shop.eppendorf.us/US-en/Laboratory-Consumables-44512/Tubes-44515/Eppendorf-Safe-Lock-Tubes-PF-8863.html" + ] + } + } + ], + "cornerOffsetFromSlot": { "x": 0, "y": 0, "z": 0 } + }, + "opentrons/usascientific_96_wellplate_2.4ml_deep/1": { + "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": "USA Scientific", + "brandId": ["1896-2000"], + "links": [ + "https://www.usascientific.com/2ml-deep96-well-plateone-bulk.aspx" + ] + }, + "metadata": { + "displayName": "USA Scientific 96 Deep Well Plate 2.4 mL", + "displayCategory": "wellPlate", + "displayVolumeUnits": "mL", + "tags": [] + }, + "dimensions": { + "xDimension": 127.8, + "yDimension": 85.5, + "zDimension": 44.1 + }, + "wells": { + "H1": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 14.4, + "y": 11.2, + "z": 2.8 + }, + "G1": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 14.4, + "y": 20.2, + "z": 2.8 + }, + "F1": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 14.4, + "y": 29.2, + "z": 2.8 + }, + "E1": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 14.4, + "y": 38.2, + "z": 2.8 + }, + "D1": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 14.4, + "y": 47.2, + "z": 2.8 + }, + "C1": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 14.4, + "y": 56.2, + "z": 2.8 + }, + "B1": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 14.4, + "y": 65.2, + "z": 2.8 + }, + "A1": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 14.4, + "y": 74.2, + "z": 2.8 + }, + "H2": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 23.4, + "y": 11.2, + "z": 2.8 + }, + "G2": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 23.4, + "y": 20.2, + "z": 2.8 + }, + "F2": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 23.4, + "y": 29.2, + "z": 2.8 + }, + "E2": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 23.4, + "y": 38.2, + "z": 2.8 + }, + "D2": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 23.4, + "y": 47.2, + "z": 2.8 + }, + "C2": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 23.4, + "y": 56.2, + "z": 2.8 + }, + "B2": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 23.4, + "y": 65.2, + "z": 2.8 + }, + "A2": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 23.4, + "y": 74.2, + "z": 2.8 + }, + "H3": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 32.4, + "y": 11.2, + "z": 2.8 + }, + "G3": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 32.4, + "y": 20.2, + "z": 2.8 + }, + "F3": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 32.4, + "y": 29.2, + "z": 2.8 + }, + "E3": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 32.4, + "y": 38.2, + "z": 2.8 + }, + "D3": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 32.4, + "y": 47.2, + "z": 2.8 + }, + "C3": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 32.4, + "y": 56.2, + "z": 2.8 + }, + "B3": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 32.4, + "y": 65.2, + "z": 2.8 + }, + "A3": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 32.4, + "y": 74.2, + "z": 2.8 + }, + "H4": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 41.4, + "y": 11.2, + "z": 2.8 + }, + "G4": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 41.4, + "y": 20.2, + "z": 2.8 + }, + "F4": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 41.4, + "y": 29.2, + "z": 2.8 + }, + "E4": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 41.4, + "y": 38.2, + "z": 2.8 + }, + "D4": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 41.4, + "y": 47.2, + "z": 2.8 + }, + "C4": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 41.4, + "y": 56.2, + "z": 2.8 + }, + "B4": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 41.4, + "y": 65.2, + "z": 2.8 + }, + "A4": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 41.4, + "y": 74.2, + "z": 2.8 + }, + "H5": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 50.4, + "y": 11.2, + "z": 2.8 + }, + "G5": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 50.4, + "y": 20.2, + "z": 2.8 + }, + "F5": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 50.4, + "y": 29.2, + "z": 2.8 + }, + "E5": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 50.4, + "y": 38.2, + "z": 2.8 + }, + "D5": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 50.4, + "y": 47.2, + "z": 2.8 + }, + "C5": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 50.4, + "y": 56.2, + "z": 2.8 + }, + "B5": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 50.4, + "y": 65.2, + "z": 2.8 + }, + "A5": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 50.4, + "y": 74.2, + "z": 2.8 + }, + "H6": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 59.4, + "y": 11.2, + "z": 2.8 + }, + "G6": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 59.4, + "y": 20.2, + "z": 2.8 + }, + "F6": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 59.4, + "y": 29.2, + "z": 2.8 + }, + "E6": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 59.4, + "y": 38.2, + "z": 2.8 + }, + "D6": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 59.4, + "y": 47.2, + "z": 2.8 + }, + "C6": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 59.4, + "y": 56.2, + "z": 2.8 + }, + "B6": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 59.4, + "y": 65.2, + "z": 2.8 + }, + "A6": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 59.4, + "y": 74.2, + "z": 2.8 + }, + "H7": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 68.4, + "y": 11.2, + "z": 2.8 + }, + "G7": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 68.4, + "y": 20.2, + "z": 2.8 + }, + "F7": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 68.4, + "y": 29.2, + "z": 2.8 + }, + "E7": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 68.4, + "y": 38.2, + "z": 2.8 + }, + "D7": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 68.4, + "y": 47.2, + "z": 2.8 + }, + "C7": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 68.4, + "y": 56.2, + "z": 2.8 + }, + "B7": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 68.4, + "y": 65.2, + "z": 2.8 + }, + "A7": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 68.4, + "y": 74.2, + "z": 2.8 + }, + "H8": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 77.4, + "y": 11.2, + "z": 2.8 + }, + "G8": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 77.4, + "y": 20.2, + "z": 2.8 + }, + "F8": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 77.4, + "y": 29.2, + "z": 2.8 + }, + "E8": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 77.4, + "y": 38.2, + "z": 2.8 + }, + "D8": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 77.4, + "y": 47.2, + "z": 2.8 + }, + "C8": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 77.4, + "y": 56.2, + "z": 2.8 + }, + "B8": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 77.4, + "y": 65.2, + "z": 2.8 + }, + "A8": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 77.4, + "y": 74.2, + "z": 2.8 + }, + "H9": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 86.4, + "y": 11.2, + "z": 2.8 + }, + "G9": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 86.4, + "y": 20.2, + "z": 2.8 + }, + "F9": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 86.4, + "y": 29.2, + "z": 2.8 + }, + "E9": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 86.4, + "y": 38.2, + "z": 2.8 + }, + "D9": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 86.4, + "y": 47.2, + "z": 2.8 + }, + "C9": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 86.4, + "y": 56.2, + "z": 2.8 + }, + "B9": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 86.4, + "y": 65.2, + "z": 2.8 + }, + "A9": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 86.4, + "y": 74.2, + "z": 2.8 + }, + "H10": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 95.4, + "y": 11.2, + "z": 2.8 + }, + "G10": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 95.4, + "y": 20.2, + "z": 2.8 + }, + "F10": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 95.4, + "y": 29.2, + "z": 2.8 + }, + "E10": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 95.4, + "y": 38.2, + "z": 2.8 + }, + "D10": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 95.4, + "y": 47.2, + "z": 2.8 + }, + "C10": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 95.4, + "y": 56.2, + "z": 2.8 + }, + "B10": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 95.4, + "y": 65.2, + "z": 2.8 + }, + "A10": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 95.4, + "y": 74.2, + "z": 2.8 + }, + "H11": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 104.4, + "y": 11.2, + "z": 2.8 + }, + "G11": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 104.4, + "y": 20.2, + "z": 2.8 + }, + "F11": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 104.4, + "y": 29.2, + "z": 2.8 + }, + "E11": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 104.4, + "y": 38.2, + "z": 2.8 + }, + "D11": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 104.4, + "y": 47.2, + "z": 2.8 + }, + "C11": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 104.4, + "y": 56.2, + "z": 2.8 + }, + "B11": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 104.4, + "y": 65.2, + "z": 2.8 + }, + "A11": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 104.4, + "y": 74.2, + "z": 2.8 + }, + "H12": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 113.4, + "y": 11.2, + "z": 2.8 + }, + "G12": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 113.4, + "y": 20.2, + "z": 2.8 + }, + "F12": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 113.4, + "y": 29.2, + "z": 2.8 + }, + "E12": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 113.4, + "y": 38.2, + "z": 2.8 + }, + "D12": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 113.4, + "y": 47.2, + "z": 2.8 + }, + "C12": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 113.4, + "y": 56.2, + "z": 2.8 + }, + "B12": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 113.4, + "y": 65.2, + "z": 2.8 + }, + "A12": { + "depth": 41.3, + "shape": "rectangular", + "xDimension": 8.2, + "yDimension": 8.2, + "totalLiquidVolume": 2400, + "x": 113.4, + "y": 74.2, + "z": 2.8 + } + }, + "groups": [ + { + "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" + ], + "metadata": { "wellBottomShape": "u" } + } + ], + "parameters": { + "format": "96Standard", + "isTiprack": false, + "isMagneticModuleCompatible": true, + "magneticModuleEngageHeight": 14.94, + "loadName": "usascientific_96_wellplate_2.4ml_deep" + }, + "namespace": "opentrons", + "version": 1, + "schemaVersion": 2, + "cornerOffsetFromSlot": { "x": 0, "y": 0, "z": 0 } + } + }, + "schemaVersion": 3, + "commands": [] +} diff --git a/protocol-designer/src/load-file/migration/6_0_0.ts b/protocol-designer/src/load-file/migration/6_0_0.ts index 6d030978f33..400a56d5988 100644 --- a/protocol-designer/src/load-file/migration/6_0_0.ts +++ b/protocol-designer/src/load-file/migration/6_0_0.ts @@ -12,6 +12,9 @@ import { uuid } from '../../utils' // and labware access parameters, renames AirGap to aspirate, and removes all temporal properties from labware, pipettes, // and module keys such as slot, mount // and renames well to wellName +import { + LoadLiquidCreateCommand +} from '../../../../shared-data/protocol/types/schemaV6/command/setup'; import type { LoadPipetteCreateCommand, LoadModuleCreateCommand, @@ -32,6 +35,7 @@ interface DesignerApplicationData { liquidGroupId: string } > + ingredLocations: { [labwareId: string]: { [wellName: string]: { [liquidId: string]: { volume: number } } } } } const PD_VERSION = '6.0.0' @@ -85,7 +89,7 @@ const migrateCommands = ( export const migrateFile = ( appData: ProtocolFileV5<DesignerApplicationData> ): ProtocolFile => { - const { pipettes, labware, modules, commands } = appData + const { pipettes, labware, modules, commands, designerApplication } = appData const loadPipetteCommands: LoadPipetteCreateCommand[] = map( pipettes, (pipette, pipetteId) => { @@ -131,25 +135,82 @@ export const migrateFile = ( } ) + let loadLiquidCommands: LoadLiquidCreateCommand[] = [] + + let labwareIdsByLiquidId: { [liquidId: string]: string[] } = {} + + if (designerApplication?.data?.ingredLocations != null && designerApplication?.data?.ingredients != null) { + Object.keys(designerApplication?.data?.ingredients).forEach(liquidId => { + if (designerApplication?.data?.ingredLocations != null) { + for (const [labwareId, liquidsByWellName] of Object.entries(designerApplication?.data?.ingredLocations)) { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + for (const [_wellName, volumeByLiquidId] of Object.entries(liquidsByWellName)) { + if (liquidId in volumeByLiquidId) { + if (labwareIdsByLiquidId[liquidId] == null) { + labwareIdsByLiquidId = { + ...labwareIdsByLiquidId, + [liquidId]: [labwareId] + } + } else if (!labwareIdsByLiquidId[liquidId].includes(labwareId)) { + labwareIdsByLiquidId = { + ...labwareIdsByLiquidId, + [liquidId]: [...labwareIdsByLiquidId[liquidId], labwareId] + } + } + } + } + } + } + }) + + loadLiquidCommands = reduce<{ [liquidId: string]: string[] }, LoadLiquidCreateCommand[]>(labwareIdsByLiquidId, (acc, labwareIds, liquidId) => { + const commands: LoadLiquidCreateCommand[] = labwareIds.map(labwareId => { + const volumeByWell = reduce(designerApplication.data?.ingredLocations[labwareId], (acc, volumesByLiquidId, wellName) => { + if (liquidId in volumesByLiquidId) { + return { + ...acc, + [wellName]: volumesByLiquidId[liquidId].volume + } + } else { + return { ...acc } + } + }, {}) + + const loadLiquidCommand: LoadLiquidCreateCommand = { + commandType: "loadLiquid", + key: uuid(), + params: { + liquidId, + labwareId, + volumeByWell + } + } + return loadLiquidCommand + }) + return [...commands, ...acc] + + }, []) + } + const migratedV5Commands = migrateCommands(commands) const liquids: ProtocolFile['liquids'] = appData.designerApplication?.data?.ingredients != null ? reduce( - appData.designerApplication?.data?.ingredients, - (acc, liquidData, liquidId) => { - return { - ...acc, - [liquidId]: { - displayName: liquidData.name, - description: liquidData.description, - }, - } - }, - {} - ) + appData.designerApplication?.data?.ingredients, + (acc, liquidData, liquidId) => { + return { + ...acc, + [liquidId]: { + displayName: liquidData.name, + description: liquidData.description, + }, + } + }, + {} + ) : // eslint-disable-next-line @typescript-eslint/consistent-type-assertions - ({} as ProtocolFile['liquids']) + ({} as ProtocolFile['liquids']) return { ...appData, @@ -168,7 +229,7 @@ export const migrateFile = ( modules: migrateModules(appData.modules), liquids, commands: [ - // TODO: generate load liquid commands https://github.com/Opentrons/opentrons/issues/9702 + ...loadLiquidCommands, ...loadPipetteCommands, ...loadModuleCommands, ...loadLabwareCommands, diff --git a/protocol-designer/src/load-file/migration/__tests__/6_0_0.test.ts b/protocol-designer/src/load-file/migration/__tests__/6_0_0.test.ts index d64d537e8d1..c92b70a7212 100644 --- a/protocol-designer/src/load-file/migration/__tests__/6_0_0.test.ts +++ b/protocol-designer/src/load-file/migration/__tests__/6_0_0.test.ts @@ -1,5 +1,6 @@ import { migrateFile } from '../6_0_0' import _oldProtocol from 'protocol-designer/fixtures/protocol/5/doItAllV5.json' +import _oldProtocolMultipleLiquids from 'protocol-designer/fixtures/protocol/5/multipleLiquids.json' import type { ProtocolFile, ProtocolFileV5 } from '@opentrons/shared-data' const oldProtocol = (_oldProtocol as unknown) as ProtocolFileV5<any> @@ -140,6 +141,196 @@ describe('v6 migration', () => { ] expect(loadLabwareCommands).toEqual(expectedLoadLabwareCommaands) }) + it('creates loadLiquid commands', () => { + const expectedLoadLiquidCommands = [ + { + key: expect.any(String), + commandType: 'loadLiquid', + params: { + liquidId: '0', + labwareId: '6114d3d0-b759-11ec-81e8-7fa12dc3e861:opentrons/opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap/1', // this is just taken from the fixture + volumeByWell: { + A1: 222, + B1: 222, + C1: 222, + D1: 222, + A2: 222, + B2: 222, + C2: 222, + D2: 222, + }, + }, + }, + { + key: expect.any(String), + commandType: 'loadLiquid', + params: { + liquidId: '1', + labwareId: '6114d3d0-b759-11ec-81e8-7fa12dc3e861:opentrons/opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap/1', // this is just taken from the fixture + volumeByWell: { + A3: 333, + B3: 333, + C3: 333, + D3: 333, + A4: 333, + B4: 333, + C4: 333, + D4: 333, + }, + }, + }, + { + key: expect.any(String), + commandType: 'loadLiquid', + params: { + liquidId: '2', + labwareId: '6114d3d0-b759-11ec-81e8-7fa12dc3e861:opentrons/opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap/1', // this is just taken from the fixture + volumeByWell: { + A5: 444, + B5: 444, + C5: 444, + D5: 444, + A6: 444, + B6: 444, + C6: 444, + D6: 444, + }, + }, + }, + { + key: expect.any(String), + commandType: 'loadLiquid', + params: { + liquidId: '0', + labwareId: '64c66a20-b759-11ec-81e8-7fa12dc3e861:opentrons/usascientific_96_wellplate_2.4ml_deep/1', // this is just taken from the fixture + volumeByWell: { + A1: 555, + B1: 555, + C1: 555, + D1: 555, + E1: 555, + F1: 555, + G1: 555, + H1: 555, + A2: 555, + B2: 555, + C2: 555, + D2: 555, + E2: 555, + F2: 555, + G2: 555, + H2: 555, + A3: 555, + B3: 555, + C3: 555, + D3: 555, + E3: 555, + F3: 555, + G3: 555, + H3: 555, + }, + }, + }, + { + key: expect.any(String), + commandType: 'loadLiquid', + params: { + liquidId: '1', + labwareId: '64c66a20-b759-11ec-81e8-7fa12dc3e861:opentrons/usascientific_96_wellplate_2.4ml_deep/1', // this is just taken from the fixture + volumeByWell: { + A4: 666, + B4: 666, + C4: 666, + D4: 666, + E4: 666, + F4: 666, + G4: 666, + H4: 666, + A5: 666, + B5: 666, + C5: 666, + D5: 666, + E5: 666, + F5: 666, + G5: 666, + H5: 666, + A6: 666, + B6: 666, + C6: 666, + D6: 666, + E6: 666, + F6: 666, + G6: 666, + H6: 666, + }, + }, + }, + { + key: expect.any(String), + commandType: 'loadLiquid', + params: { + liquidId: '2', + labwareId: '64c66a20-b759-11ec-81e8-7fa12dc3e861:opentrons/usascientific_96_wellplate_2.4ml_deep/1', // this is just taken from the fixture + volumeByWell: { + A7: 777, + B7: 777, + C7: 777, + D7: 777, + E7: 777, + F7: 777, + G7: 777, + H7: 777, + A8: 777, + B8: 777, + C8: 777, + D8: 777, + E8: 777, + F8: 777, + G8: 777, + H8: 777, + A9: 777, + B9: 777, + C9: 777, + D9: 777, + E9: 777, + F9: 777, + G9: 777, + H9: 777, + A10: 777, + B10: 777, + C10: 777, + D10: 777, + E10: 777, + F10: 777, + G10: 777, + H10: 777, + A11: 777, + B11: 777, + C11: 777, + D11: 777, + E11: 777, + F11: 777, + G11: 777, + H11: 777, + A12: 777, + B12: 777, + C12: 777, + D12: 777, + E12: 777, + F12: 777, + G12: 777, + H12: 777 + } + }, + } + ] + + const migratedLiquidsFile = migrateFile(_oldProtocolMultipleLiquids as any) + const loadLiquidCommands = migratedLiquidsFile.commands.filter( + command => command.commandType === 'loadLiquid' + ) + expect(loadLiquidCommands).toEqual(expect.arrayContaining(expectedLoadLiquidCommands)) + }) it('replaces air gap commands with aspirate commands', () => { const expectedConvertedAirgapCommands = [ { diff --git a/shared-data/protocol/types/schemaV6/command/gantry.ts b/shared-data/protocol/types/schemaV6/command/gantry.ts index c24b2baf991..e9803b6b5fe 100644 --- a/shared-data/protocol/types/schemaV6/command/gantry.ts +++ b/shared-data/protocol/types/schemaV6/command/gantry.ts @@ -1,58 +1,58 @@ -import type { CommonCommandRunTimeInfo } from '.' +import type { CommonCommandRunTimeInfo, CommonCommandCreateInfo } from '.' import type { MotorAxis } from '../../../../js/types' -export interface MoveToSlotCreateCommand { +export interface MoveToSlotCreateCommand extends CommonCommandCreateInfo { commandType: 'moveToSlot' params: MoveToSlotParams } export interface MoveToSlotRunTimeCommand extends CommonCommandRunTimeInfo, - MoveToSlotCreateCommand { + MoveToSlotCreateCommand { result: {} } -export interface MoveToWellCreateCommand { +export interface MoveToWellCreateCommand extends CommonCommandCreateInfo { commandType: 'moveToWell' params: MoveToWellParams } export interface MoveToWellRunTimeCommand extends CommonCommandRunTimeInfo, - MoveToWellCreateCommand { + MoveToWellCreateCommand { result: {} } -export interface MoveToCoordinatesCreateCommand { +export interface MoveToCoordinatesCreateCommand extends CommonCommandCreateInfo { commandType: 'moveToCoordinates' params: MoveToCoordinatesParams } export interface MoveToCoordinatesRunTimeCommand extends CommonCommandRunTimeInfo, - MoveToCoordinatesCreateCommand { + MoveToCoordinatesCreateCommand { result: {} } -export interface MoveRelativeCreateCommand { +export interface MoveRelativeCreateCommand extends CommonCommandCreateInfo { commandType: 'moveRelative' params: MoveRelativeParams } export interface MoveRelativeRunTimeCommand extends CommonCommandRunTimeInfo, - MoveRelativeCreateCommand { + MoveRelativeCreateCommand { result: {} } -export interface SavePositionCreateCommand { +export interface SavePositionCreateCommand extends CommonCommandCreateInfo { commandType: 'savePosition' params: SavePositionParams } export interface SavePositionRunTimeCommand extends CommonCommandRunTimeInfo, - SavePositionCreateCommand { + SavePositionCreateCommand { result: {} } -export interface HomeCreateCommand { +export interface HomeCreateCommand extends CommonCommandCreateInfo { commandType: 'home' params: HomeParams } export interface HomeRunTimeCommand extends CommonCommandRunTimeInfo, - HomeCreateCommand { + HomeCreateCommand { result: {} } export type GantryRunTimeCommand = diff --git a/shared-data/protocol/types/schemaV6/command/index.ts b/shared-data/protocol/types/schemaV6/command/index.ts index af7b107b6fb..739c88cd001 100644 --- a/shared-data/protocol/types/schemaV6/command/index.ts +++ b/shared-data/protocol/types/schemaV6/command/index.ts @@ -18,7 +18,7 @@ import type { export type CommandStatus = 'queued' | 'running' | 'succeeded' | 'failed' export interface CommonCommandRunTimeInfo { - key: string + key?: string id: string status: CommandStatus error: string | null diff --git a/shared-data/protocol/types/schemaV6/command/module.ts b/shared-data/protocol/types/schemaV6/command/module.ts index 8ab9bc5de7f..b936a44f156 100644 --- a/shared-data/protocol/types/schemaV6/command/module.ts +++ b/shared-data/protocol/types/schemaV6/command/module.ts @@ -1,4 +1,4 @@ -import { CommonCommandRunTimeInfo } from '.' +import type { CommonCommandRunTimeInfo, CommonCommandCreateInfo } from '.' export type ModuleRunTimeCommand = | MagneticModuleEngageMagnetRunTimeCommand @@ -47,202 +47,202 @@ export type ModuleCreateCommand = | HeaterShakerStopShakeCreateCommand | HeaterShakerStartSetTargetTemperatureCreateCommand -export interface MagneticModuleEngageMagnetCreateCommand { +export interface MagneticModuleEngageMagnetCreateCommand extends CommonCommandCreateInfo { commandType: 'magneticModule/engageMagnet' params: EngageMagnetParams } export interface MagneticModuleEngageMagnetRunTimeCommand extends CommonCommandRunTimeInfo, - MagneticModuleEngageMagnetCreateCommand { + MagneticModuleEngageMagnetCreateCommand { result: any } -export interface MagneticModuleDisengageMagnetCreateCommand { +export interface MagneticModuleDisengageMagnetCreateCommand extends CommonCommandCreateInfo { commandType: 'magneticModule/disengageMagnet' params: ModuleOnlyParams } export interface MagneticModuleDisengageMagnetRunTimeCommand extends CommonCommandRunTimeInfo, - MagneticModuleDisengageMagnetCreateCommand { + MagneticModuleDisengageMagnetCreateCommand { result: any } -export interface TemperatureModuleSetTargetTemperatureCreateCommand { +export interface TemperatureModuleSetTargetTemperatureCreateCommand extends CommonCommandCreateInfo { commandType: 'temperatureModule/setTargetTemperature' params: TemperatureParams } export interface TemperatureModuleSetTargetTemperatureRunTimeCommand extends CommonCommandRunTimeInfo, - TemperatureModuleSetTargetTemperatureCreateCommand { + TemperatureModuleSetTargetTemperatureCreateCommand { result: any } -export interface TemperatureModuleDeactivateCreateCommand { +export interface TemperatureModuleDeactivateCreateCommand extends CommonCommandCreateInfo { commandType: 'temperatureModule/deactivate' params: ModuleOnlyParams } export interface TemperatureModuleDeactivateRunTimeCommand extends CommonCommandRunTimeInfo, - TemperatureModuleDeactivateCreateCommand { + TemperatureModuleDeactivateCreateCommand { result: any } -export interface TemperatureModuleAwaitTemperatureCreateCommand { +export interface TemperatureModuleAwaitTemperatureCreateCommand extends CommonCommandCreateInfo { commandType: 'temperatureModule/awaitTemperature' params: TemperatureParams } export interface TemperatureModuleAwaitTemperatureRunTimeCommand extends CommonCommandRunTimeInfo, - TemperatureModuleAwaitTemperatureCreateCommand { + TemperatureModuleAwaitTemperatureCreateCommand { result: any } -export interface TCSetTargetBlockTemperatureCreateCommand { +export interface TCSetTargetBlockTemperatureCreateCommand extends CommonCommandCreateInfo { commandType: 'thermocycler/setTargetBlockTemperature' params: ThermocyclerSetTargetBlockTemperatureParams } export interface TCSetTargetBlockTemperatureRunTimeCommand extends CommonCommandRunTimeInfo, - TCSetTargetBlockTemperatureCreateCommand { + TCSetTargetBlockTemperatureCreateCommand { result: any } -export interface TCSetTargetLidTemperatureCreateCommand { +export interface TCSetTargetLidTemperatureCreateCommand extends CommonCommandCreateInfo { commandType: 'thermocycler/setTargetLidTemperature' params: TemperatureParams } export interface TCSetTargetLidTemperatureRunTimeCommand extends CommonCommandRunTimeInfo, - TCSetTargetLidTemperatureCreateCommand { + TCSetTargetLidTemperatureCreateCommand { result: any } -export interface TCAwaitBlockTemperatureCreateCommand { +export interface TCAwaitBlockTemperatureCreateCommand extends CommonCommandCreateInfo { commandType: 'thermocycler/awaitBlockTemperature' params: TemperatureParams } export interface TCAwaitBlockTemperatureRunTimeCommand extends CommonCommandRunTimeInfo, - TCAwaitBlockTemperatureCreateCommand { + TCAwaitBlockTemperatureCreateCommand { result: any } -export interface TCAwaitLidTemperatureCreateCommand { +export interface TCAwaitLidTemperatureCreateCommand extends CommonCommandCreateInfo { commandType: 'thermocycler/awaitLidTemperature' params: TemperatureParams } export interface TCAwaitLidTemperatureRunTimeCommand extends CommonCommandRunTimeInfo, - TCAwaitLidTemperatureCreateCommand { + TCAwaitLidTemperatureCreateCommand { result: any } -export interface TCOpenLidCreateCommand { +export interface TCOpenLidCreateCommand extends CommonCommandCreateInfo { commandType: 'thermocycler/openLid' params: ModuleOnlyParams } export interface TCOpenLidRunTimeCommand extends CommonCommandRunTimeInfo, - TCOpenLidCreateCommand { + TCOpenLidCreateCommand { result: any } -export interface TCCloseLidCreateCommand { +export interface TCCloseLidCreateCommand extends CommonCommandCreateInfo { commandType: 'thermocycler/closeLid' params: ModuleOnlyParams } export interface TCCloseLidRunTimeCommand extends CommonCommandRunTimeInfo, - TCCloseLidCreateCommand { + TCCloseLidCreateCommand { result: any } -export interface TCDeactivateBlockCreateCommand { +export interface TCDeactivateBlockCreateCommand extends CommonCommandCreateInfo { commandType: 'thermocycler/deactivateBlock' params: ModuleOnlyParams } export interface TCDeactivateBlockRunTimeCommand extends CommonCommandRunTimeInfo, - TCDeactivateBlockCreateCommand { + TCDeactivateBlockCreateCommand { result: any } -export interface TCDeactivateLidCreateCommand { +export interface TCDeactivateLidCreateCommand extends CommonCommandCreateInfo { commandType: 'thermocycler/deactivateLid' params: ModuleOnlyParams } export interface TCDeactivateLidRunTimeCommand extends CommonCommandRunTimeInfo, - TCDeactivateLidCreateCommand { + TCDeactivateLidCreateCommand { result: any } -export interface TCRunProfileCreateCommand { +export interface TCRunProfileCreateCommand extends CommonCommandCreateInfo { commandType: 'thermocycler/runProfile' params: TCProfileParams } export interface TCRunProfileRunTimeCommand extends CommonCommandRunTimeInfo, - TCRunProfileCreateCommand { + TCRunProfileCreateCommand { result: any } -export interface TCAwaitProfileCompleteCreateCommand { +export interface TCAwaitProfileCompleteCreateCommand extends CommonCommandCreateInfo { commandType: 'thermocycler/awaitProfileComplete' params: ModuleOnlyParams } export interface TCAwaitProfileCompleteRunTimeCommand extends CommonCommandRunTimeInfo, - TCAwaitProfileCompleteCreateCommand { + TCAwaitProfileCompleteCreateCommand { result: any } -export interface HeaterShakerStartSetTargetTemperatureCreateCommand { +export interface HeaterShakerStartSetTargetTemperatureCreateCommand extends CommonCommandCreateInfo { commandType: 'heaterShakerModule/startSetTargetTemperature' params: TemperatureParams } export interface HeaterShakerStartSetTargetTemperatureRunTimeCommand extends CommonCommandRunTimeInfo, - HeaterShakerStartSetTargetTemperatureCreateCommand { + HeaterShakerStartSetTargetTemperatureCreateCommand { result: any } -export interface HeaterShakerAwaitTemperatureCreateCommand { +export interface HeaterShakerAwaitTemperatureCreateCommand extends CommonCommandCreateInfo { commandType: 'heaterShakerModule/awaitTemperature' params: ModuleOnlyParams } export interface HeaterShakerAwaitTemperatureRunTimeCommand extends CommonCommandRunTimeInfo, - HeaterShakerAwaitTemperatureCreateCommand { + HeaterShakerAwaitTemperatureCreateCommand { result: any } -export interface HeaterShakerSetTargetShakeSpeedCreateCommand { +export interface HeaterShakerSetTargetShakeSpeedCreateCommand extends CommonCommandCreateInfo { commandType: 'heaterShakerModule/setTargetShakeSpeed' params: ShakeSpeedParams } export interface HeaterShakerSetTargetShakeSpeedRunTimeCommand extends CommonCommandRunTimeInfo, - HeaterShakerSetTargetShakeSpeedCreateCommand { + HeaterShakerSetTargetShakeSpeedCreateCommand { result: any } -export interface HeaterShakerDeactivateHeaterCreateCommand { +export interface HeaterShakerDeactivateHeaterCreateCommand extends CommonCommandCreateInfo { commandType: 'heaterShakerModule/deactivateHeater' params: ModuleOnlyParams } export interface HeaterShakerDeactivateHeaterRunTimeCommand extends CommonCommandRunTimeInfo, - HeaterShakerDeactivateHeaterCreateCommand { + HeaterShakerDeactivateHeaterCreateCommand { result: any } -export interface HeaterShakerOpenLatchCreateCommand { +export interface HeaterShakerOpenLatchCreateCommand extends CommonCommandCreateInfo { commandType: 'heaterShakerModule/openLatch' params: ModuleOnlyParams } export interface HeaterShakerOpenLatchRunTimeCommand extends CommonCommandRunTimeInfo, - HeaterShakerOpenLatchCreateCommand { + HeaterShakerOpenLatchCreateCommand { result: any } -export interface HeaterShakerCloseLatchCreateCommand { +export interface HeaterShakerCloseLatchCreateCommand extends CommonCommandCreateInfo { commandType: 'heaterShakerModule/closeLatch' params: ModuleOnlyParams } export interface HeaterShakerCloseLatchRunTimeCommand extends CommonCommandRunTimeInfo, - HeaterShakerCloseLatchCreateCommand { + HeaterShakerCloseLatchCreateCommand { result: any } -export interface HeaterShakerStopShakeCreateCommand { +export interface HeaterShakerStopShakeCreateCommand extends CommonCommandCreateInfo { commandType: 'heaterShakerModule/stopShake' params: ModuleOnlyParams } export interface HeaterShakerStopShakeRunTimeCommand extends CommonCommandRunTimeInfo, - HeaterShakerStopShakeCreateCommand { + HeaterShakerStopShakeCreateCommand { result: any } diff --git a/shared-data/protocol/types/schemaV6/command/pipetting.ts b/shared-data/protocol/types/schemaV6/command/pipetting.ts index b76e9249ce7..69d5bcaa105 100644 --- a/shared-data/protocol/types/schemaV6/command/pipetting.ts +++ b/shared-data/protocol/types/schemaV6/command/pipetting.ts @@ -1,4 +1,5 @@ import { CommonCommandRunTimeInfo } from '.' +import { CommonCommandCreateInfo } from '../../../../lib/protocol/types/schemaV6/command/index.d'; export type PipettingRunTimeCommand = | AspirateRunTimeCommand | DispenseRunTimeCommand @@ -18,76 +19,58 @@ export type PipettingCreateCommand = | PickUpTipCreateCommand | DropTipCreateCommand -export interface AspirateCreateCommand { +export interface AspirateCreateCommand extends CommonCommandCreateInfo { commandType: 'aspirate' params: AspDispAirgapParams } export interface AspirateRunTimeCommand extends CommonCommandRunTimeInfo, - AspirateCreateCommand { + AspirateCreateCommand { result: BasicLiquidHandlingResult } -export interface DispenseCreateCommand { +export interface DispenseCreateCommand extends CommonCommandCreateInfo { commandType: 'dispense' params: AspDispAirgapParams } export interface DispenseRunTimeCommand extends CommonCommandRunTimeInfo, - DispenseCreateCommand { + DispenseCreateCommand { result: BasicLiquidHandlingResult } -export interface AspirateAirGapCreateCommand { - commandType: 'aspirateAirGap' - params: AspDispAirgapParams -} -export interface AspirateAirGapRunTimeCommand - extends CommonCommandRunTimeInfo, - AspirateAirGapCreateCommand { - result: BasicLiquidHandlingResult -} -export interface DispenseAirGapCreateCommand { - commandType: 'dispenseAirGap' - params: AspDispAirgapParams -} -export interface DispenseAirGapRunTimeCommand - extends CommonCommandRunTimeInfo, - DispenseAirGapCreateCommand { - result: BasicLiquidHandlingResult -} -export interface BlowoutCreateCommand { +export interface BlowoutCreateCommand extends CommonCommandCreateInfo { commandType: 'blowout' params: BlowoutParams } export interface BlowoutRunTimeCommand extends CommonCommandRunTimeInfo, - BlowoutCreateCommand { + BlowoutCreateCommand { result: BasicLiquidHandlingResult } -export interface TouchTipCreateCommand { +export interface TouchTipCreateCommand extends CommonCommandCreateInfo { commandType: 'touchTip' params: TouchTipParams } export interface TouchTipRunTimeCommand extends CommonCommandRunTimeInfo, - TouchTipCreateCommand { + TouchTipCreateCommand { result: BasicLiquidHandlingResult } -export interface PickUpTipCreateCommand { +export interface PickUpTipCreateCommand extends CommonCommandCreateInfo { commandType: 'pickUpTip' params: PickUpTipParams } export interface PickUpTipRunTimeCommand extends CommonCommandRunTimeInfo, - PickUpTipCreateCommand { + PickUpTipCreateCommand { result: any } -export interface DropTipCreateCommand { +export interface DropTipCreateCommand extends CommonCommandCreateInfo { commandType: 'dropTip' params: DropTipParams } export interface DropTipRunTimeCommand extends CommonCommandRunTimeInfo, - DropTipCreateCommand { + DropTipCreateCommand { result: any } diff --git a/shared-data/protocol/types/schemaV6/command/setup.ts b/shared-data/protocol/types/schemaV6/command/setup.ts index 01e0a18de2e..c73ba7c2697 100644 --- a/shared-data/protocol/types/schemaV6/command/setup.ts +++ b/shared-data/protocol/types/schemaV6/command/setup.ts @@ -1,51 +1,52 @@ -import { +import type { CommonCommandRunTimeInfo, + CommonCommandCreateInfo, LabwareDefinition2, LabwareOffset, PipetteName, ModuleModel, } from '../../../../js' -export interface LoadPipetteCreateCommand { +export interface LoadPipetteCreateCommand extends CommonCommandCreateInfo { commandType: 'loadPipette' params: LoadPipetteParams } export interface LoadPipetteRunTimeCommand extends CommonCommandRunTimeInfo, - Omit<LoadPipetteCreateCommand, 'params'> { + Omit<LoadPipetteCreateCommand, 'params'> { params: LoadPipetteParams & { pipetteName: PipetteName } result: LoadPipetteResult } -export interface LoadLabwareCreateCommand { +export interface LoadLabwareCreateCommand extends CommonCommandCreateInfo { commandType: 'loadLabware' params: LoadLabwareParams } export interface LoadLabwareRunTimeCommand extends CommonCommandRunTimeInfo, - LoadLabwareCreateCommand { + LoadLabwareCreateCommand { result: LoadLabwareResult } -export interface LoadModuleCreateCommand { +export interface LoadModuleCreateCommand extends CommonCommandCreateInfo { commandType: 'loadModule' params: LoadModuleParams } export interface LoadModuleRunTimeCommand extends CommonCommandRunTimeInfo, - Omit<LoadModuleCreateCommand, 'params'> { + Omit<LoadModuleCreateCommand, 'params'> { params: LoadModuleParams & { model: ModuleModel } result: LoadModuleResult } -export interface LoadLiquidCreateCommand { +export interface LoadLiquidCreateCommand extends CommonCommandCreateInfo { commandType: 'loadLiquid' params: LoadLiquidParams } export interface LoadLiquidRunTimeCommand extends CommonCommandRunTimeInfo, - LoadLiquidCreateCommand { + LoadLiquidCreateCommand { result: LoadLiquidResult } diff --git a/shared-data/protocol/types/schemaV6/command/timing.ts b/shared-data/protocol/types/schemaV6/command/timing.ts index e40b27e6a8e..e9cad012760 100644 --- a/shared-data/protocol/types/schemaV6/command/timing.ts +++ b/shared-data/protocol/types/schemaV6/command/timing.ts @@ -1,11 +1,11 @@ -import { CommonCommandRunTimeInfo } from '.' -export interface TimingCreateCommand { +import type { CommonCommandRunTimeInfo, CommonCommandCreateInfo } from '.' +export interface TimingCreateCommand extends CommonCommandCreateInfo { commandType: 'delay' params: DelayParams } export interface TimingRunTimeCommand extends CommonCommandRunTimeInfo, - TimingCreateCommand { + TimingCreateCommand { result: {} } @@ -14,13 +14,13 @@ interface DelayParams { message?: string } -export interface PauseCreateCommand { +export interface PauseCreateCommand extends CommonCommandCreateInfo { commandType: 'pause' params: PauseParams } export interface PauseRunTimeCommand extends CommonCommandRunTimeInfo, - PauseCreateCommand { + PauseCreateCommand { result: any } From beee5ecfce153783c3eb568ddc6eebc5890c3926 Mon Sep 17 00:00:00 2001 From: Shlok Amin <shlokamin@me.com> Date: Mon, 11 Apr 2022 10:37:32 -0400 Subject: [PATCH 2/6] refactor load liquid command getter --- .../src/file-data/selectors/fileCreator.ts | 77 ++++++++++--------- .../src/load-file/migration/6_0_0.ts | 76 +----------------- .../migration/utils/getLoadLiquidCommands.ts | 75 ++++++++++++++++++ 3 files changed, 119 insertions(+), 109 deletions(-) create mode 100644 protocol-designer/src/load-file/migration/utils/getLoadLiquidCommands.ts diff --git a/protocol-designer/src/file-data/selectors/fileCreator.ts b/protocol-designer/src/file-data/selectors/fileCreator.ts index 16d3734c712..b8a211234d7 100644 --- a/protocol-designer/src/file-data/selectors/fileCreator.ts +++ b/protocol-designer/src/file-data/selectors/fileCreator.ts @@ -16,6 +16,7 @@ import { uuid } from '../../utils' import { selectors as ingredSelectors } from '../../labware-ingred/selectors' import { selectors as stepFormSelectors } from '../../step-forms' import { selectors as uiLabwareSelectors } from '../../ui/labware' +import { getLoadLiquidCommands } from '../../load-file/migration/utils/getLoadLiquidCommands' import { DEFAULT_MM_FROM_BOTTOM_ASPIRATE, DEFAULT_MM_FROM_BOTTOM_DISPENSE, @@ -32,8 +33,8 @@ import type { CreateCommand, ProtocolFile, } from '@opentrons/shared-data/protocol/types/schemaV6' -import { Selector } from '../../types' -import { +import type { Selector } from '../../types' +import type { LoadLabwareCreateCommand, LoadModuleCreateCommand, LoadPipetteCreateCommand, @@ -108,6 +109,39 @@ export const createFile: Selector<ProtocolFile> = createSelector( const { author, description, created } = fileMetadata const name = fileMetadata.protocolName || 'untitled' const lastModified = fileMetadata.lastModified + // TODO: Ian 2018-07-10 allow user to save steps in JSON file, even if those + // step never have saved forms. + // (We could just export the `steps` reducer, but we've sunset it) + const savedOrderedStepIds = orderedStepIds.filter( + stepId => savedStepForms[stepId] + ) + const designerApplication = { + name: 'opentrons/protocol-designer', + version: applicationVersion, + data: { + _internalAppBuildDate, + defaultValues: { + // TODO: Ian 2019-06-13 load these into redux and always get them from redux, not constants.js + // This `defaultValues` key is not yet read by anything, but is populated here for auditability + // and so that later we can do #3587 without a PD migration + aspirate_mmFromBottom: DEFAULT_MM_FROM_BOTTOM_ASPIRATE, + dispense_mmFromBottom: DEFAULT_MM_FROM_BOTTOM_DISPENSE, + touchTip_mmFromTop: DEFAULT_MM_TOUCH_TIP_OFFSET_FROM_TOP, + blowout_mmFromTop: DEFAULT_MM_BLOWOUT_OFFSET_FROM_TOP, + }, + pipetteTiprackAssignments: mapValues( + pipetteEntities, + ( + p: typeof pipetteEntities[keyof typeof pipetteEntities] + ): string | null | undefined => p.tiprackDefURI + ), + dismissedWarnings, + ingredients, + ingredLocations, + savedStepForms, + orderedStepIds: savedOrderedStepIds, + }, + } const pipettes: ProtocolFile['pipettes'] = mapValues( initialRobotState.pipettes, @@ -179,6 +213,8 @@ export const createFile: Selector<ProtocolFile> = createSelector( return loadLabwareCommand } ) + + const loadLiquidCommands = getLoadLiquidCommands(designerApplication) const modules: ProtocolFile['modules'] = mapValues( moduleEntities, (moduleEntity: ModuleEntity, moduleId: string) => ({ @@ -203,12 +239,7 @@ export const createFile: Selector<ProtocolFile> = createSelector( return loadModuleCommand } ) - // TODO: Ian 2018-07-10 allow user to save steps in JSON file, even if those - // step never have saved forms. - // (We could just export the `steps` reducer, but we've sunset it) - const savedOrderedStepIds = orderedStepIds.filter( - stepId => savedStepForms[stepId] - ) + const labwareDefinitions = getLabwareDefinitionsInUse( labwareEntities, pipetteEntities, @@ -218,7 +249,7 @@ export const createFile: Selector<ProtocolFile> = createSelector( ...loadPipetteCommands, ...loadLabwareCommands, ...loadModuleCommands, - // TODO: generate load liquid commands https://github.com/Opentrons/opentrons/issues/9702 + ...loadLiquidCommands ] const nonLoadCommands: CreateCommand[] = flatMap( @@ -240,33 +271,7 @@ export const createFile: Selector<ProtocolFile> = createSelector( subcategory: null, tags: [], }, - designerApplication: { - name: 'opentrons/protocol-designer', - version: applicationVersion, - data: { - _internalAppBuildDate, - defaultValues: { - // TODO: Ian 2019-06-13 load these into redux and always get them from redux, not constants.js - // This `defaultValues` key is not yet read by anything, but is populated here for auditability - // and so that later we can do #3587 without a PD migration - aspirate_mmFromBottom: DEFAULT_MM_FROM_BOTTOM_ASPIRATE, - dispense_mmFromBottom: DEFAULT_MM_FROM_BOTTOM_DISPENSE, - touchTip_mmFromTop: DEFAULT_MM_TOUCH_TIP_OFFSET_FROM_TOP, - blowout_mmFromTop: DEFAULT_MM_BLOWOUT_OFFSET_FROM_TOP, - }, - pipetteTiprackAssignments: mapValues( - pipetteEntities, - ( - p: typeof pipetteEntities[keyof typeof pipetteEntities] - ): string | null | undefined => p.tiprackDefURI - ), - dismissedWarnings, - ingredients, - ingredLocations, - savedStepForms, - orderedStepIds: savedOrderedStepIds, - }, - }, + designerApplication, robot: { model: OT2_STANDARD_MODEL, deckId: OT2_STANDARD_DECKID, diff --git a/protocol-designer/src/load-file/migration/6_0_0.ts b/protocol-designer/src/load-file/migration/6_0_0.ts index 400a56d5988..eddccd2bc3c 100644 --- a/protocol-designer/src/load-file/migration/6_0_0.ts +++ b/protocol-designer/src/load-file/migration/6_0_0.ts @@ -12,9 +12,7 @@ import { uuid } from '../../utils' // and labware access parameters, renames AirGap to aspirate, and removes all temporal properties from labware, pipettes, // and module keys such as slot, mount // and renames well to wellName -import { - LoadLiquidCreateCommand -} from '../../../../shared-data/protocol/types/schemaV6/command/setup'; +import { getLoadLiquidCommands } from './utils/getLoadLiquidCommands'; import type { LoadPipetteCreateCommand, LoadModuleCreateCommand, @@ -24,19 +22,7 @@ import type { CreateCommand, ProtocolFile, } from '@opentrons/shared-data/protocol/types/schemaV6' - -interface DesignerApplicationData { - ingredients: Record< - string, - { - name: string - description: string | null - serialize: boolean - liquidGroupId: string - } - > - ingredLocations: { [labwareId: string]: { [wellName: string]: { [liquidId: string]: { volume: number } } } } -} +import type { DesignerApplicationData } from './utils/getLoadLiquidCommands'; const PD_VERSION = '6.0.0' const SCHEMA_VERSION = 6 @@ -135,63 +121,7 @@ export const migrateFile = ( } ) - let loadLiquidCommands: LoadLiquidCreateCommand[] = [] - - let labwareIdsByLiquidId: { [liquidId: string]: string[] } = {} - - if (designerApplication?.data?.ingredLocations != null && designerApplication?.data?.ingredients != null) { - Object.keys(designerApplication?.data?.ingredients).forEach(liquidId => { - if (designerApplication?.data?.ingredLocations != null) { - for (const [labwareId, liquidsByWellName] of Object.entries(designerApplication?.data?.ingredLocations)) { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - for (const [_wellName, volumeByLiquidId] of Object.entries(liquidsByWellName)) { - if (liquidId in volumeByLiquidId) { - if (labwareIdsByLiquidId[liquidId] == null) { - labwareIdsByLiquidId = { - ...labwareIdsByLiquidId, - [liquidId]: [labwareId] - } - } else if (!labwareIdsByLiquidId[liquidId].includes(labwareId)) { - labwareIdsByLiquidId = { - ...labwareIdsByLiquidId, - [liquidId]: [...labwareIdsByLiquidId[liquidId], labwareId] - } - } - } - } - } - } - }) - - loadLiquidCommands = reduce<{ [liquidId: string]: string[] }, LoadLiquidCreateCommand[]>(labwareIdsByLiquidId, (acc, labwareIds, liquidId) => { - const commands: LoadLiquidCreateCommand[] = labwareIds.map(labwareId => { - const volumeByWell = reduce(designerApplication.data?.ingredLocations[labwareId], (acc, volumesByLiquidId, wellName) => { - if (liquidId in volumesByLiquidId) { - return { - ...acc, - [wellName]: volumesByLiquidId[liquidId].volume - } - } else { - return { ...acc } - } - }, {}) - - const loadLiquidCommand: LoadLiquidCreateCommand = { - commandType: "loadLiquid", - key: uuid(), - params: { - liquidId, - labwareId, - volumeByWell - } - } - return loadLiquidCommand - }) - return [...commands, ...acc] - - }, []) - } - + const loadLiquidCommands = getLoadLiquidCommands(designerApplication) const migratedV5Commands = migrateCommands(commands) const liquids: ProtocolFile['liquids'] = diff --git a/protocol-designer/src/load-file/migration/utils/getLoadLiquidCommands.ts b/protocol-designer/src/load-file/migration/utils/getLoadLiquidCommands.ts new file mode 100644 index 00000000000..46bdc3119e7 --- /dev/null +++ b/protocol-designer/src/load-file/migration/utils/getLoadLiquidCommands.ts @@ -0,0 +1,75 @@ +import reduce from 'lodash/reduce' +import { uuid } from '../../../utils' +import type { ProtocolFileV5 } from "@opentrons/shared-data" +import type { LoadLiquidCreateCommand } from "@opentrons/shared-data/protocol/types/schemaV6/command/setup" + +export interface DesignerApplicationData { + ingredients: Record< + string, + { + name: string | null | undefined + description: string | null | undefined + serialize: boolean + } + > + ingredLocations: { [labwareId: string]: { [wellName: string]: { [liquidId: string]: { volume: number } } } } +} + +export const getLoadLiquidCommands = (designerApplication: ProtocolFileV5<DesignerApplicationData>['designerApplication']): LoadLiquidCreateCommand[] => { + let loadLiquidCommands: LoadLiquidCreateCommand[] = [] + + let labwareIdsByLiquidId: { [liquidId: string]: string[] } = {} + + if (designerApplication?.data?.ingredLocations != null && designerApplication?.data?.ingredients != null) { + Object.keys(designerApplication?.data?.ingredients).forEach(liquidId => { + if (designerApplication?.data?.ingredLocations != null) { + for (const [labwareId, liquidsByWellName] of Object.entries(designerApplication?.data?.ingredLocations)) { + Object.values(liquidsByWellName).forEach(volumeByLiquidId => { + if (liquidId in volumeByLiquidId) { + if (labwareIdsByLiquidId[liquidId] == null) { + labwareIdsByLiquidId = { + ...labwareIdsByLiquidId, + [liquidId]: [labwareId] + } + } else if (!labwareIdsByLiquidId[liquidId].includes(labwareId)) { + labwareIdsByLiquidId = { + ...labwareIdsByLiquidId, + [liquidId]: [...labwareIdsByLiquidId[liquidId], labwareId] + } + } + } + }) + } + } + }) + + loadLiquidCommands = reduce<{ [liquidId: string]: string[] }, LoadLiquidCreateCommand[]>(labwareIdsByLiquidId, (acc, labwareIds, liquidId) => { + const commands: LoadLiquidCreateCommand[] = labwareIds.map(labwareId => { + const volumeByWell = reduce(designerApplication.data?.ingredLocations[labwareId], (acc, volumesByLiquidId, wellName) => { + if (liquidId in volumesByLiquidId) { + return { + ...acc, + [wellName]: volumesByLiquidId[liquidId].volume + } + } else { + return { ...acc } + } + }, {}) + + const loadLiquidCommand: LoadLiquidCreateCommand = { + commandType: "loadLiquid", + key: uuid(), + params: { + liquidId, + labwareId, + volumeByWell + } + } + return loadLiquidCommand + }) + return [...commands, ...acc] + + }, []) + } + return loadLiquidCommands +} \ No newline at end of file From d19ea91271d34b415e9cbae8b52c34446c441ad3 Mon Sep 17 00:00:00 2001 From: Shlok Amin <shlokamin@me.com> Date: Mon, 11 Apr 2022 10:39:03 -0400 Subject: [PATCH 3/6] format --- .../src/file-data/selectors/fileCreator.ts | 2 +- .../src/load-file/migration/6_0_0.ts | 30 ++-- .../migration/__tests__/6_0_0.test.ts | 28 ++-- .../migration/utils/getLoadLiquidCommands.ts | 147 ++++++++++-------- .../protocol/types/schemaV6/command/gantry.ts | 15 +- .../protocol/types/schemaV6/command/module.ts | 98 +++++++----- .../types/schemaV6/command/pipetting.ts | 14 +- .../protocol/types/schemaV6/command/setup.ts | 8 +- .../protocol/types/schemaV6/command/timing.ts | 4 +- 9 files changed, 198 insertions(+), 148 deletions(-) diff --git a/protocol-designer/src/file-data/selectors/fileCreator.ts b/protocol-designer/src/file-data/selectors/fileCreator.ts index b8a211234d7..6ff946fe27c 100644 --- a/protocol-designer/src/file-data/selectors/fileCreator.ts +++ b/protocol-designer/src/file-data/selectors/fileCreator.ts @@ -249,7 +249,7 @@ export const createFile: Selector<ProtocolFile> = createSelector( ...loadPipetteCommands, ...loadLabwareCommands, ...loadModuleCommands, - ...loadLiquidCommands + ...loadLiquidCommands, ] const nonLoadCommands: CreateCommand[] = flatMap( diff --git a/protocol-designer/src/load-file/migration/6_0_0.ts b/protocol-designer/src/load-file/migration/6_0_0.ts index eddccd2bc3c..f16361ee123 100644 --- a/protocol-designer/src/load-file/migration/6_0_0.ts +++ b/protocol-designer/src/load-file/migration/6_0_0.ts @@ -12,7 +12,7 @@ import { uuid } from '../../utils' // and labware access parameters, renames AirGap to aspirate, and removes all temporal properties from labware, pipettes, // and module keys such as slot, mount // and renames well to wellName -import { getLoadLiquidCommands } from './utils/getLoadLiquidCommands'; +import { getLoadLiquidCommands } from './utils/getLoadLiquidCommands' import type { LoadPipetteCreateCommand, LoadModuleCreateCommand, @@ -22,7 +22,7 @@ import type { CreateCommand, ProtocolFile, } from '@opentrons/shared-data/protocol/types/schemaV6' -import type { DesignerApplicationData } from './utils/getLoadLiquidCommands'; +import type { DesignerApplicationData } from './utils/getLoadLiquidCommands' const PD_VERSION = '6.0.0' const SCHEMA_VERSION = 6 @@ -127,20 +127,20 @@ export const migrateFile = ( const liquids: ProtocolFile['liquids'] = appData.designerApplication?.data?.ingredients != null ? reduce( - appData.designerApplication?.data?.ingredients, - (acc, liquidData, liquidId) => { - return { - ...acc, - [liquidId]: { - displayName: liquidData.name, - description: liquidData.description, - }, - } - }, - {} - ) + appData.designerApplication?.data?.ingredients, + (acc, liquidData, liquidId) => { + return { + ...acc, + [liquidId]: { + displayName: liquidData.name, + description: liquidData.description, + }, + } + }, + {} + ) : // eslint-disable-next-line @typescript-eslint/consistent-type-assertions - ({} as ProtocolFile['liquids']) + ({} as ProtocolFile['liquids']) return { ...appData, diff --git a/protocol-designer/src/load-file/migration/__tests__/6_0_0.test.ts b/protocol-designer/src/load-file/migration/__tests__/6_0_0.test.ts index c92b70a7212..1a27d3b2c73 100644 --- a/protocol-designer/src/load-file/migration/__tests__/6_0_0.test.ts +++ b/protocol-designer/src/load-file/migration/__tests__/6_0_0.test.ts @@ -148,7 +148,8 @@ describe('v6 migration', () => { commandType: 'loadLiquid', params: { liquidId: '0', - labwareId: '6114d3d0-b759-11ec-81e8-7fa12dc3e861:opentrons/opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap/1', // this is just taken from the fixture + labwareId: + '6114d3d0-b759-11ec-81e8-7fa12dc3e861:opentrons/opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap/1', // this is just taken from the fixture volumeByWell: { A1: 222, B1: 222, @@ -166,7 +167,8 @@ describe('v6 migration', () => { commandType: 'loadLiquid', params: { liquidId: '1', - labwareId: '6114d3d0-b759-11ec-81e8-7fa12dc3e861:opentrons/opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap/1', // this is just taken from the fixture + labwareId: + '6114d3d0-b759-11ec-81e8-7fa12dc3e861:opentrons/opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap/1', // this is just taken from the fixture volumeByWell: { A3: 333, B3: 333, @@ -184,7 +186,8 @@ describe('v6 migration', () => { commandType: 'loadLiquid', params: { liquidId: '2', - labwareId: '6114d3d0-b759-11ec-81e8-7fa12dc3e861:opentrons/opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap/1', // this is just taken from the fixture + labwareId: + '6114d3d0-b759-11ec-81e8-7fa12dc3e861:opentrons/opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap/1', // this is just taken from the fixture volumeByWell: { A5: 444, B5: 444, @@ -202,7 +205,8 @@ describe('v6 migration', () => { commandType: 'loadLiquid', params: { liquidId: '0', - labwareId: '64c66a20-b759-11ec-81e8-7fa12dc3e861:opentrons/usascientific_96_wellplate_2.4ml_deep/1', // this is just taken from the fixture + labwareId: + '64c66a20-b759-11ec-81e8-7fa12dc3e861:opentrons/usascientific_96_wellplate_2.4ml_deep/1', // this is just taken from the fixture volumeByWell: { A1: 555, B1: 555, @@ -236,7 +240,8 @@ describe('v6 migration', () => { commandType: 'loadLiquid', params: { liquidId: '1', - labwareId: '64c66a20-b759-11ec-81e8-7fa12dc3e861:opentrons/usascientific_96_wellplate_2.4ml_deep/1', // this is just taken from the fixture + labwareId: + '64c66a20-b759-11ec-81e8-7fa12dc3e861:opentrons/usascientific_96_wellplate_2.4ml_deep/1', // this is just taken from the fixture volumeByWell: { A4: 666, B4: 666, @@ -270,7 +275,8 @@ describe('v6 migration', () => { commandType: 'loadLiquid', params: { liquidId: '2', - labwareId: '64c66a20-b759-11ec-81e8-7fa12dc3e861:opentrons/usascientific_96_wellplate_2.4ml_deep/1', // this is just taken from the fixture + labwareId: + '64c66a20-b759-11ec-81e8-7fa12dc3e861:opentrons/usascientific_96_wellplate_2.4ml_deep/1', // this is just taken from the fixture volumeByWell: { A7: 777, B7: 777, @@ -319,17 +325,19 @@ describe('v6 migration', () => { E12: 777, F12: 777, G12: 777, - H12: 777 - } + H12: 777, + }, }, - } + }, ] const migratedLiquidsFile = migrateFile(_oldProtocolMultipleLiquids as any) const loadLiquidCommands = migratedLiquidsFile.commands.filter( command => command.commandType === 'loadLiquid' ) - expect(loadLiquidCommands).toEqual(expect.arrayContaining(expectedLoadLiquidCommands)) + expect(loadLiquidCommands).toEqual( + expect.arrayContaining(expectedLoadLiquidCommands) + ) }) it('replaces air gap commands with aspirate commands', () => { const expectedConvertedAirgapCommands = [ diff --git a/protocol-designer/src/load-file/migration/utils/getLoadLiquidCommands.ts b/protocol-designer/src/load-file/migration/utils/getLoadLiquidCommands.ts index 46bdc3119e7..0b693adbb9e 100644 --- a/protocol-designer/src/load-file/migration/utils/getLoadLiquidCommands.ts +++ b/protocol-designer/src/load-file/migration/utils/getLoadLiquidCommands.ts @@ -1,75 +1,98 @@ import reduce from 'lodash/reduce' import { uuid } from '../../../utils' -import type { ProtocolFileV5 } from "@opentrons/shared-data" -import type { LoadLiquidCreateCommand } from "@opentrons/shared-data/protocol/types/schemaV6/command/setup" +import type { ProtocolFileV5 } from '@opentrons/shared-data' +import type { LoadLiquidCreateCommand } from '@opentrons/shared-data/protocol/types/schemaV6/command/setup' export interface DesignerApplicationData { - ingredients: Record< - string, - { - name: string | null | undefined - description: string | null | undefined - serialize: boolean - } - > - ingredLocations: { [labwareId: string]: { [wellName: string]: { [liquidId: string]: { volume: number } } } } + ingredients: Record< + string, + { + name: string | null | undefined + description: string | null | undefined + serialize: boolean + } + > + ingredLocations: { + [labwareId: string]: { + [wellName: string]: { [liquidId: string]: { volume: number } } + } + } } -export const getLoadLiquidCommands = (designerApplication: ProtocolFileV5<DesignerApplicationData>['designerApplication']): LoadLiquidCreateCommand[] => { - let loadLiquidCommands: LoadLiquidCreateCommand[] = [] +export const getLoadLiquidCommands = ( + designerApplication: ProtocolFileV5<DesignerApplicationData>['designerApplication'] +): LoadLiquidCreateCommand[] => { + let loadLiquidCommands: LoadLiquidCreateCommand[] = [] - let labwareIdsByLiquidId: { [liquidId: string]: string[] } = {} + let labwareIdsByLiquidId: { [liquidId: string]: string[] } = {} - if (designerApplication?.data?.ingredLocations != null && designerApplication?.data?.ingredients != null) { - Object.keys(designerApplication?.data?.ingredients).forEach(liquidId => { - if (designerApplication?.data?.ingredLocations != null) { - for (const [labwareId, liquidsByWellName] of Object.entries(designerApplication?.data?.ingredLocations)) { - Object.values(liquidsByWellName).forEach(volumeByLiquidId => { - if (liquidId in volumeByLiquidId) { - if (labwareIdsByLiquidId[liquidId] == null) { - labwareIdsByLiquidId = { - ...labwareIdsByLiquidId, - [liquidId]: [labwareId] - } - } else if (!labwareIdsByLiquidId[liquidId].includes(labwareId)) { - labwareIdsByLiquidId = { - ...labwareIdsByLiquidId, - [liquidId]: [...labwareIdsByLiquidId[liquidId], labwareId] - } - } - } - }) + if ( + designerApplication?.data?.ingredLocations != null && + designerApplication?.data?.ingredients != null + ) { + Object.keys(designerApplication?.data?.ingredients).forEach(liquidId => { + if (designerApplication?.data?.ingredLocations != null) { + for (const [labwareId, liquidsByWellName] of Object.entries( + designerApplication?.data?.ingredLocations + )) { + Object.values(liquidsByWellName).forEach(volumeByLiquidId => { + if (liquidId in volumeByLiquidId) { + if (labwareIdsByLiquidId[liquidId] == null) { + labwareIdsByLiquidId = { + ...labwareIdsByLiquidId, + [liquidId]: [labwareId], } + } else if (!labwareIdsByLiquidId[liquidId].includes(labwareId)) { + labwareIdsByLiquidId = { + ...labwareIdsByLiquidId, + [liquidId]: [...labwareIdsByLiquidId[liquidId], labwareId], + } + } } - }) - - loadLiquidCommands = reduce<{ [liquidId: string]: string[] }, LoadLiquidCreateCommand[]>(labwareIdsByLiquidId, (acc, labwareIds, liquidId) => { - const commands: LoadLiquidCreateCommand[] = labwareIds.map(labwareId => { - const volumeByWell = reduce(designerApplication.data?.ingredLocations[labwareId], (acc, volumesByLiquidId, wellName) => { - if (liquidId in volumesByLiquidId) { - return { - ...acc, - [wellName]: volumesByLiquidId[liquidId].volume - } - } else { - return { ...acc } - } - }, {}) + }) + } + } + }) - const loadLiquidCommand: LoadLiquidCreateCommand = { - commandType: "loadLiquid", - key: uuid(), - params: { - liquidId, - labwareId, - volumeByWell - } + loadLiquidCommands = reduce< + { [liquidId: string]: string[] }, + LoadLiquidCreateCommand[] + >( + labwareIdsByLiquidId, + (acc, labwareIds, liquidId) => { + const commands: LoadLiquidCreateCommand[] = labwareIds.map( + labwareId => { + const volumeByWell = reduce( + designerApplication.data?.ingredLocations[labwareId], + (acc, volumesByLiquidId, wellName) => { + if (liquidId in volumesByLiquidId) { + return { + ...acc, + [wellName]: volumesByLiquidId[liquidId].volume, + } + } else { + return { ...acc } } - return loadLiquidCommand - }) - return [...commands, ...acc] + }, + {} + ) - }, []) - } - return loadLiquidCommands -} \ No newline at end of file + const loadLiquidCommand: LoadLiquidCreateCommand = { + commandType: 'loadLiquid', + key: uuid(), + params: { + liquidId, + labwareId, + volumeByWell, + }, + } + return loadLiquidCommand + } + ) + return [...commands, ...acc] + }, + [] + ) + } + return loadLiquidCommands +} diff --git a/shared-data/protocol/types/schemaV6/command/gantry.ts b/shared-data/protocol/types/schemaV6/command/gantry.ts index e9803b6b5fe..09232cf1453 100644 --- a/shared-data/protocol/types/schemaV6/command/gantry.ts +++ b/shared-data/protocol/types/schemaV6/command/gantry.ts @@ -7,7 +7,7 @@ export interface MoveToSlotCreateCommand extends CommonCommandCreateInfo { } export interface MoveToSlotRunTimeCommand extends CommonCommandRunTimeInfo, - MoveToSlotCreateCommand { + MoveToSlotCreateCommand { result: {} } export interface MoveToWellCreateCommand extends CommonCommandCreateInfo { @@ -16,16 +16,17 @@ export interface MoveToWellCreateCommand extends CommonCommandCreateInfo { } export interface MoveToWellRunTimeCommand extends CommonCommandRunTimeInfo, - MoveToWellCreateCommand { + MoveToWellCreateCommand { result: {} } -export interface MoveToCoordinatesCreateCommand extends CommonCommandCreateInfo { +export interface MoveToCoordinatesCreateCommand + extends CommonCommandCreateInfo { commandType: 'moveToCoordinates' params: MoveToCoordinatesParams } export interface MoveToCoordinatesRunTimeCommand extends CommonCommandRunTimeInfo, - MoveToCoordinatesCreateCommand { + MoveToCoordinatesCreateCommand { result: {} } export interface MoveRelativeCreateCommand extends CommonCommandCreateInfo { @@ -34,7 +35,7 @@ export interface MoveRelativeCreateCommand extends CommonCommandCreateInfo { } export interface MoveRelativeRunTimeCommand extends CommonCommandRunTimeInfo, - MoveRelativeCreateCommand { + MoveRelativeCreateCommand { result: {} } export interface SavePositionCreateCommand extends CommonCommandCreateInfo { @@ -43,7 +44,7 @@ export interface SavePositionCreateCommand extends CommonCommandCreateInfo { } export interface SavePositionRunTimeCommand extends CommonCommandRunTimeInfo, - SavePositionCreateCommand { + SavePositionCreateCommand { result: {} } export interface HomeCreateCommand extends CommonCommandCreateInfo { @@ -52,7 +53,7 @@ export interface HomeCreateCommand extends CommonCommandCreateInfo { } export interface HomeRunTimeCommand extends CommonCommandRunTimeInfo, - HomeCreateCommand { + HomeCreateCommand { result: {} } export type GantryRunTimeCommand = diff --git a/shared-data/protocol/types/schemaV6/command/module.ts b/shared-data/protocol/types/schemaV6/command/module.ts index b936a44f156..c0ad6ad3c10 100644 --- a/shared-data/protocol/types/schemaV6/command/module.ts +++ b/shared-data/protocol/types/schemaV6/command/module.ts @@ -47,85 +47,94 @@ export type ModuleCreateCommand = | HeaterShakerStopShakeCreateCommand | HeaterShakerStartSetTargetTemperatureCreateCommand -export interface MagneticModuleEngageMagnetCreateCommand extends CommonCommandCreateInfo { +export interface MagneticModuleEngageMagnetCreateCommand + extends CommonCommandCreateInfo { commandType: 'magneticModule/engageMagnet' params: EngageMagnetParams } export interface MagneticModuleEngageMagnetRunTimeCommand extends CommonCommandRunTimeInfo, - MagneticModuleEngageMagnetCreateCommand { + MagneticModuleEngageMagnetCreateCommand { result: any } -export interface MagneticModuleDisengageMagnetCreateCommand extends CommonCommandCreateInfo { +export interface MagneticModuleDisengageMagnetCreateCommand + extends CommonCommandCreateInfo { commandType: 'magneticModule/disengageMagnet' params: ModuleOnlyParams } export interface MagneticModuleDisengageMagnetRunTimeCommand extends CommonCommandRunTimeInfo, - MagneticModuleDisengageMagnetCreateCommand { + MagneticModuleDisengageMagnetCreateCommand { result: any } -export interface TemperatureModuleSetTargetTemperatureCreateCommand extends CommonCommandCreateInfo { +export interface TemperatureModuleSetTargetTemperatureCreateCommand + extends CommonCommandCreateInfo { commandType: 'temperatureModule/setTargetTemperature' params: TemperatureParams } export interface TemperatureModuleSetTargetTemperatureRunTimeCommand extends CommonCommandRunTimeInfo, - TemperatureModuleSetTargetTemperatureCreateCommand { + TemperatureModuleSetTargetTemperatureCreateCommand { result: any } -export interface TemperatureModuleDeactivateCreateCommand extends CommonCommandCreateInfo { +export interface TemperatureModuleDeactivateCreateCommand + extends CommonCommandCreateInfo { commandType: 'temperatureModule/deactivate' params: ModuleOnlyParams } export interface TemperatureModuleDeactivateRunTimeCommand extends CommonCommandRunTimeInfo, - TemperatureModuleDeactivateCreateCommand { + TemperatureModuleDeactivateCreateCommand { result: any } -export interface TemperatureModuleAwaitTemperatureCreateCommand extends CommonCommandCreateInfo { +export interface TemperatureModuleAwaitTemperatureCreateCommand + extends CommonCommandCreateInfo { commandType: 'temperatureModule/awaitTemperature' params: TemperatureParams } export interface TemperatureModuleAwaitTemperatureRunTimeCommand extends CommonCommandRunTimeInfo, - TemperatureModuleAwaitTemperatureCreateCommand { + TemperatureModuleAwaitTemperatureCreateCommand { result: any } -export interface TCSetTargetBlockTemperatureCreateCommand extends CommonCommandCreateInfo { +export interface TCSetTargetBlockTemperatureCreateCommand + extends CommonCommandCreateInfo { commandType: 'thermocycler/setTargetBlockTemperature' params: ThermocyclerSetTargetBlockTemperatureParams } export interface TCSetTargetBlockTemperatureRunTimeCommand extends CommonCommandRunTimeInfo, - TCSetTargetBlockTemperatureCreateCommand { + TCSetTargetBlockTemperatureCreateCommand { result: any } -export interface TCSetTargetLidTemperatureCreateCommand extends CommonCommandCreateInfo { +export interface TCSetTargetLidTemperatureCreateCommand + extends CommonCommandCreateInfo { commandType: 'thermocycler/setTargetLidTemperature' params: TemperatureParams } export interface TCSetTargetLidTemperatureRunTimeCommand extends CommonCommandRunTimeInfo, - TCSetTargetLidTemperatureCreateCommand { + TCSetTargetLidTemperatureCreateCommand { result: any } -export interface TCAwaitBlockTemperatureCreateCommand extends CommonCommandCreateInfo { +export interface TCAwaitBlockTemperatureCreateCommand + extends CommonCommandCreateInfo { commandType: 'thermocycler/awaitBlockTemperature' params: TemperatureParams } export interface TCAwaitBlockTemperatureRunTimeCommand extends CommonCommandRunTimeInfo, - TCAwaitBlockTemperatureCreateCommand { + TCAwaitBlockTemperatureCreateCommand { result: any } -export interface TCAwaitLidTemperatureCreateCommand extends CommonCommandCreateInfo { +export interface TCAwaitLidTemperatureCreateCommand + extends CommonCommandCreateInfo { commandType: 'thermocycler/awaitLidTemperature' params: TemperatureParams } export interface TCAwaitLidTemperatureRunTimeCommand extends CommonCommandRunTimeInfo, - TCAwaitLidTemperatureCreateCommand { + TCAwaitLidTemperatureCreateCommand { result: any } export interface TCOpenLidCreateCommand extends CommonCommandCreateInfo { @@ -134,7 +143,7 @@ export interface TCOpenLidCreateCommand extends CommonCommandCreateInfo { } export interface TCOpenLidRunTimeCommand extends CommonCommandRunTimeInfo, - TCOpenLidCreateCommand { + TCOpenLidCreateCommand { result: any } export interface TCCloseLidCreateCommand extends CommonCommandCreateInfo { @@ -143,16 +152,17 @@ export interface TCCloseLidCreateCommand extends CommonCommandCreateInfo { } export interface TCCloseLidRunTimeCommand extends CommonCommandRunTimeInfo, - TCCloseLidCreateCommand { + TCCloseLidCreateCommand { result: any } -export interface TCDeactivateBlockCreateCommand extends CommonCommandCreateInfo { +export interface TCDeactivateBlockCreateCommand + extends CommonCommandCreateInfo { commandType: 'thermocycler/deactivateBlock' params: ModuleOnlyParams } export interface TCDeactivateBlockRunTimeCommand extends CommonCommandRunTimeInfo, - TCDeactivateBlockCreateCommand { + TCDeactivateBlockCreateCommand { result: any } export interface TCDeactivateLidCreateCommand extends CommonCommandCreateInfo { @@ -161,7 +171,7 @@ export interface TCDeactivateLidCreateCommand extends CommonCommandCreateInfo { } export interface TCDeactivateLidRunTimeCommand extends CommonCommandRunTimeInfo, - TCDeactivateLidCreateCommand { + TCDeactivateLidCreateCommand { result: any } export interface TCRunProfileCreateCommand extends CommonCommandCreateInfo { @@ -170,79 +180,87 @@ export interface TCRunProfileCreateCommand extends CommonCommandCreateInfo { } export interface TCRunProfileRunTimeCommand extends CommonCommandRunTimeInfo, - TCRunProfileCreateCommand { + TCRunProfileCreateCommand { result: any } -export interface TCAwaitProfileCompleteCreateCommand extends CommonCommandCreateInfo { +export interface TCAwaitProfileCompleteCreateCommand + extends CommonCommandCreateInfo { commandType: 'thermocycler/awaitProfileComplete' params: ModuleOnlyParams } export interface TCAwaitProfileCompleteRunTimeCommand extends CommonCommandRunTimeInfo, - TCAwaitProfileCompleteCreateCommand { + TCAwaitProfileCompleteCreateCommand { result: any } -export interface HeaterShakerStartSetTargetTemperatureCreateCommand extends CommonCommandCreateInfo { +export interface HeaterShakerStartSetTargetTemperatureCreateCommand + extends CommonCommandCreateInfo { commandType: 'heaterShakerModule/startSetTargetTemperature' params: TemperatureParams } export interface HeaterShakerStartSetTargetTemperatureRunTimeCommand extends CommonCommandRunTimeInfo, - HeaterShakerStartSetTargetTemperatureCreateCommand { + HeaterShakerStartSetTargetTemperatureCreateCommand { result: any } -export interface HeaterShakerAwaitTemperatureCreateCommand extends CommonCommandCreateInfo { +export interface HeaterShakerAwaitTemperatureCreateCommand + extends CommonCommandCreateInfo { commandType: 'heaterShakerModule/awaitTemperature' params: ModuleOnlyParams } export interface HeaterShakerAwaitTemperatureRunTimeCommand extends CommonCommandRunTimeInfo, - HeaterShakerAwaitTemperatureCreateCommand { + HeaterShakerAwaitTemperatureCreateCommand { result: any } -export interface HeaterShakerSetTargetShakeSpeedCreateCommand extends CommonCommandCreateInfo { +export interface HeaterShakerSetTargetShakeSpeedCreateCommand + extends CommonCommandCreateInfo { commandType: 'heaterShakerModule/setTargetShakeSpeed' params: ShakeSpeedParams } export interface HeaterShakerSetTargetShakeSpeedRunTimeCommand extends CommonCommandRunTimeInfo, - HeaterShakerSetTargetShakeSpeedCreateCommand { + HeaterShakerSetTargetShakeSpeedCreateCommand { result: any } -export interface HeaterShakerDeactivateHeaterCreateCommand extends CommonCommandCreateInfo { +export interface HeaterShakerDeactivateHeaterCreateCommand + extends CommonCommandCreateInfo { commandType: 'heaterShakerModule/deactivateHeater' params: ModuleOnlyParams } export interface HeaterShakerDeactivateHeaterRunTimeCommand extends CommonCommandRunTimeInfo, - HeaterShakerDeactivateHeaterCreateCommand { + HeaterShakerDeactivateHeaterCreateCommand { result: any } -export interface HeaterShakerOpenLatchCreateCommand extends CommonCommandCreateInfo { +export interface HeaterShakerOpenLatchCreateCommand + extends CommonCommandCreateInfo { commandType: 'heaterShakerModule/openLatch' params: ModuleOnlyParams } export interface HeaterShakerOpenLatchRunTimeCommand extends CommonCommandRunTimeInfo, - HeaterShakerOpenLatchCreateCommand { + HeaterShakerOpenLatchCreateCommand { result: any } -export interface HeaterShakerCloseLatchCreateCommand extends CommonCommandCreateInfo { +export interface HeaterShakerCloseLatchCreateCommand + extends CommonCommandCreateInfo { commandType: 'heaterShakerModule/closeLatch' params: ModuleOnlyParams } export interface HeaterShakerCloseLatchRunTimeCommand extends CommonCommandRunTimeInfo, - HeaterShakerCloseLatchCreateCommand { + HeaterShakerCloseLatchCreateCommand { result: any } -export interface HeaterShakerStopShakeCreateCommand extends CommonCommandCreateInfo { +export interface HeaterShakerStopShakeCreateCommand + extends CommonCommandCreateInfo { commandType: 'heaterShakerModule/stopShake' params: ModuleOnlyParams } export interface HeaterShakerStopShakeRunTimeCommand extends CommonCommandRunTimeInfo, - HeaterShakerStopShakeCreateCommand { + HeaterShakerStopShakeCreateCommand { result: any } diff --git a/shared-data/protocol/types/schemaV6/command/pipetting.ts b/shared-data/protocol/types/schemaV6/command/pipetting.ts index 69d5bcaa105..8a84e1966b1 100644 --- a/shared-data/protocol/types/schemaV6/command/pipetting.ts +++ b/shared-data/protocol/types/schemaV6/command/pipetting.ts @@ -1,5 +1,5 @@ import { CommonCommandRunTimeInfo } from '.' -import { CommonCommandCreateInfo } from '../../../../lib/protocol/types/schemaV6/command/index.d'; +import { CommonCommandCreateInfo } from '../../../../lib/protocol/types/schemaV6/command/index.d' export type PipettingRunTimeCommand = | AspirateRunTimeCommand | DispenseRunTimeCommand @@ -25,7 +25,7 @@ export interface AspirateCreateCommand extends CommonCommandCreateInfo { } export interface AspirateRunTimeCommand extends CommonCommandRunTimeInfo, - AspirateCreateCommand { + AspirateCreateCommand { result: BasicLiquidHandlingResult } export interface DispenseCreateCommand extends CommonCommandCreateInfo { @@ -34,7 +34,7 @@ export interface DispenseCreateCommand extends CommonCommandCreateInfo { } export interface DispenseRunTimeCommand extends CommonCommandRunTimeInfo, - DispenseCreateCommand { + DispenseCreateCommand { result: BasicLiquidHandlingResult } export interface BlowoutCreateCommand extends CommonCommandCreateInfo { @@ -43,7 +43,7 @@ export interface BlowoutCreateCommand extends CommonCommandCreateInfo { } export interface BlowoutRunTimeCommand extends CommonCommandRunTimeInfo, - BlowoutCreateCommand { + BlowoutCreateCommand { result: BasicLiquidHandlingResult } export interface TouchTipCreateCommand extends CommonCommandCreateInfo { @@ -52,7 +52,7 @@ export interface TouchTipCreateCommand extends CommonCommandCreateInfo { } export interface TouchTipRunTimeCommand extends CommonCommandRunTimeInfo, - TouchTipCreateCommand { + TouchTipCreateCommand { result: BasicLiquidHandlingResult } export interface PickUpTipCreateCommand extends CommonCommandCreateInfo { @@ -61,7 +61,7 @@ export interface PickUpTipCreateCommand extends CommonCommandCreateInfo { } export interface PickUpTipRunTimeCommand extends CommonCommandRunTimeInfo, - PickUpTipCreateCommand { + PickUpTipCreateCommand { result: any } export interface DropTipCreateCommand extends CommonCommandCreateInfo { @@ -70,7 +70,7 @@ export interface DropTipCreateCommand extends CommonCommandCreateInfo { } export interface DropTipRunTimeCommand extends CommonCommandRunTimeInfo, - DropTipCreateCommand { + DropTipCreateCommand { result: any } diff --git a/shared-data/protocol/types/schemaV6/command/setup.ts b/shared-data/protocol/types/schemaV6/command/setup.ts index c73ba7c2697..383b1c154ac 100644 --- a/shared-data/protocol/types/schemaV6/command/setup.ts +++ b/shared-data/protocol/types/schemaV6/command/setup.ts @@ -13,7 +13,7 @@ export interface LoadPipetteCreateCommand extends CommonCommandCreateInfo { } export interface LoadPipetteRunTimeCommand extends CommonCommandRunTimeInfo, - Omit<LoadPipetteCreateCommand, 'params'> { + Omit<LoadPipetteCreateCommand, 'params'> { params: LoadPipetteParams & { pipetteName: PipetteName } @@ -25,7 +25,7 @@ export interface LoadLabwareCreateCommand extends CommonCommandCreateInfo { } export interface LoadLabwareRunTimeCommand extends CommonCommandRunTimeInfo, - LoadLabwareCreateCommand { + LoadLabwareCreateCommand { result: LoadLabwareResult } export interface LoadModuleCreateCommand extends CommonCommandCreateInfo { @@ -34,7 +34,7 @@ export interface LoadModuleCreateCommand extends CommonCommandCreateInfo { } export interface LoadModuleRunTimeCommand extends CommonCommandRunTimeInfo, - Omit<LoadModuleCreateCommand, 'params'> { + Omit<LoadModuleCreateCommand, 'params'> { params: LoadModuleParams & { model: ModuleModel } @@ -46,7 +46,7 @@ export interface LoadLiquidCreateCommand extends CommonCommandCreateInfo { } export interface LoadLiquidRunTimeCommand extends CommonCommandRunTimeInfo, - LoadLiquidCreateCommand { + LoadLiquidCreateCommand { result: LoadLiquidResult } diff --git a/shared-data/protocol/types/schemaV6/command/timing.ts b/shared-data/protocol/types/schemaV6/command/timing.ts index e9cad012760..c0c9daf999f 100644 --- a/shared-data/protocol/types/schemaV6/command/timing.ts +++ b/shared-data/protocol/types/schemaV6/command/timing.ts @@ -5,7 +5,7 @@ export interface TimingCreateCommand extends CommonCommandCreateInfo { } export interface TimingRunTimeCommand extends CommonCommandRunTimeInfo, - TimingCreateCommand { + TimingCreateCommand { result: {} } @@ -20,7 +20,7 @@ export interface PauseCreateCommand extends CommonCommandCreateInfo { } export interface PauseRunTimeCommand extends CommonCommandRunTimeInfo, - PauseCreateCommand { + PauseCreateCommand { result: any } From b6ec155d7d928e5c162ee10943d68c8c0cc5d15d Mon Sep 17 00:00:00 2001 From: Shlok Amin <shlokamin@me.com> Date: Mon, 11 Apr 2022 10:45:27 -0400 Subject: [PATCH 4/6] fix type errors --- .../types/schemaV6/command/pipetting.ts | 19 +++++++------------ .../src/getNextRobotStateAndWarnings/index.ts | 1 - 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/shared-data/protocol/types/schemaV6/command/pipetting.ts b/shared-data/protocol/types/schemaV6/command/pipetting.ts index 8a84e1966b1..b89e1ef6c4f 100644 --- a/shared-data/protocol/types/schemaV6/command/pipetting.ts +++ b/shared-data/protocol/types/schemaV6/command/pipetting.ts @@ -1,10 +1,7 @@ -import { CommonCommandRunTimeInfo } from '.' -import { CommonCommandCreateInfo } from '../../../../lib/protocol/types/schemaV6/command/index.d' +import type { CommonCommandRunTimeInfo, CommonCommandCreateInfo } from '.' export type PipettingRunTimeCommand = | AspirateRunTimeCommand | DispenseRunTimeCommand - | AspirateAirGapRunTimeCommand - | DispenseAirGapRunTimeCommand | BlowoutRunTimeCommand | TouchTipRunTimeCommand | PickUpTipRunTimeCommand @@ -12,8 +9,6 @@ export type PipettingRunTimeCommand = export type PipettingCreateCommand = | AspirateCreateCommand | DispenseCreateCommand - | AspirateAirGapCreateCommand - | DispenseAirGapCreateCommand | BlowoutCreateCommand | TouchTipCreateCommand | PickUpTipCreateCommand @@ -25,7 +20,7 @@ export interface AspirateCreateCommand extends CommonCommandCreateInfo { } export interface AspirateRunTimeCommand extends CommonCommandRunTimeInfo, - AspirateCreateCommand { + AspirateCreateCommand { result: BasicLiquidHandlingResult } export interface DispenseCreateCommand extends CommonCommandCreateInfo { @@ -34,7 +29,7 @@ export interface DispenseCreateCommand extends CommonCommandCreateInfo { } export interface DispenseRunTimeCommand extends CommonCommandRunTimeInfo, - DispenseCreateCommand { + DispenseCreateCommand { result: BasicLiquidHandlingResult } export interface BlowoutCreateCommand extends CommonCommandCreateInfo { @@ -43,7 +38,7 @@ export interface BlowoutCreateCommand extends CommonCommandCreateInfo { } export interface BlowoutRunTimeCommand extends CommonCommandRunTimeInfo, - BlowoutCreateCommand { + BlowoutCreateCommand { result: BasicLiquidHandlingResult } export interface TouchTipCreateCommand extends CommonCommandCreateInfo { @@ -52,7 +47,7 @@ export interface TouchTipCreateCommand extends CommonCommandCreateInfo { } export interface TouchTipRunTimeCommand extends CommonCommandRunTimeInfo, - TouchTipCreateCommand { + TouchTipCreateCommand { result: BasicLiquidHandlingResult } export interface PickUpTipCreateCommand extends CommonCommandCreateInfo { @@ -61,7 +56,7 @@ export interface PickUpTipCreateCommand extends CommonCommandCreateInfo { } export interface PickUpTipRunTimeCommand extends CommonCommandRunTimeInfo, - PickUpTipCreateCommand { + PickUpTipCreateCommand { result: any } export interface DropTipCreateCommand extends CommonCommandCreateInfo { @@ -70,7 +65,7 @@ export interface DropTipCreateCommand extends CommonCommandCreateInfo { } export interface DropTipRunTimeCommand extends CommonCommandRunTimeInfo, - DropTipCreateCommand { + DropTipCreateCommand { result: any } diff --git a/step-generation/src/getNextRobotStateAndWarnings/index.ts b/step-generation/src/getNextRobotStateAndWarnings/index.ts index e2f774efcc3..23697951461 100644 --- a/step-generation/src/getNextRobotStateAndWarnings/index.ts +++ b/step-generation/src/getNextRobotStateAndWarnings/index.ts @@ -82,7 +82,6 @@ function _getNextRobotStateAndWarningsSingleCommand( case 'touchTip': case 'delay': - case 'dispenseAirGap': case 'moveToWell': // these commands don't have any effects on the state break From d35e40fda8d8e335e4ddb446a4166cee22b578c4 Mon Sep 17 00:00:00 2001 From: Shlok Amin <shlokamin@me.com> Date: Mon, 11 Apr 2022 11:01:38 -0400 Subject: [PATCH 5/6] format --- .../protocol/types/schemaV6/command/pipetting.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/shared-data/protocol/types/schemaV6/command/pipetting.ts b/shared-data/protocol/types/schemaV6/command/pipetting.ts index b89e1ef6c4f..3059f65b729 100644 --- a/shared-data/protocol/types/schemaV6/command/pipetting.ts +++ b/shared-data/protocol/types/schemaV6/command/pipetting.ts @@ -20,7 +20,7 @@ export interface AspirateCreateCommand extends CommonCommandCreateInfo { } export interface AspirateRunTimeCommand extends CommonCommandRunTimeInfo, - AspirateCreateCommand { + AspirateCreateCommand { result: BasicLiquidHandlingResult } export interface DispenseCreateCommand extends CommonCommandCreateInfo { @@ -29,7 +29,7 @@ export interface DispenseCreateCommand extends CommonCommandCreateInfo { } export interface DispenseRunTimeCommand extends CommonCommandRunTimeInfo, - DispenseCreateCommand { + DispenseCreateCommand { result: BasicLiquidHandlingResult } export interface BlowoutCreateCommand extends CommonCommandCreateInfo { @@ -38,7 +38,7 @@ export interface BlowoutCreateCommand extends CommonCommandCreateInfo { } export interface BlowoutRunTimeCommand extends CommonCommandRunTimeInfo, - BlowoutCreateCommand { + BlowoutCreateCommand { result: BasicLiquidHandlingResult } export interface TouchTipCreateCommand extends CommonCommandCreateInfo { @@ -47,7 +47,7 @@ export interface TouchTipCreateCommand extends CommonCommandCreateInfo { } export interface TouchTipRunTimeCommand extends CommonCommandRunTimeInfo, - TouchTipCreateCommand { + TouchTipCreateCommand { result: BasicLiquidHandlingResult } export interface PickUpTipCreateCommand extends CommonCommandCreateInfo { @@ -56,7 +56,7 @@ export interface PickUpTipCreateCommand extends CommonCommandCreateInfo { } export interface PickUpTipRunTimeCommand extends CommonCommandRunTimeInfo, - PickUpTipCreateCommand { + PickUpTipCreateCommand { result: any } export interface DropTipCreateCommand extends CommonCommandCreateInfo { @@ -65,7 +65,7 @@ export interface DropTipCreateCommand extends CommonCommandCreateInfo { } export interface DropTipRunTimeCommand extends CommonCommandRunTimeInfo, - DropTipCreateCommand { + DropTipCreateCommand { result: any } From fef525c398d80efa05eaadfc722396426b6822e2 Mon Sep 17 00:00:00 2001 From: Shlok Amin <shlokamin@me.com> Date: Tue, 12 Apr 2022 17:04:18 -0400 Subject: [PATCH 6/6] refactor liquid command generator and add tests --- .../file-data/__tests__/createFile.test.ts | 17 ++ .../src/file-data/selectors/fileCreator.ts | 5 +- .../src/load-file/migration/6_0_0.ts | 5 +- .../migration/__tests__/6_0_0.test.ts | 224 ++---------------- .../__tests__/getLoadLiquidCommands.test.ts | 206 ++++++++++++++++ .../migration/utils/getLoadLiquidCommands.ts | 17 +- 6 files changed, 263 insertions(+), 211 deletions(-) create mode 100644 protocol-designer/src/load-file/migration/utils/__tests__/getLoadLiquidCommands.test.ts diff --git a/protocol-designer/src/file-data/__tests__/createFile.test.ts b/protocol-designer/src/file-data/__tests__/createFile.test.ts index c9be91d8366..df98a4d70e4 100644 --- a/protocol-designer/src/file-data/__tests__/createFile.test.ts +++ b/protocol-designer/src/file-data/__tests__/createFile.test.ts @@ -11,6 +11,7 @@ import { fixtureP300Single, } from '@opentrons/shared-data/pipette/fixtures/name' import { LabwareDefinition2 } from '@opentrons/shared-data' +import { getLoadLiquidCommands } from '../../load-file/migration/utils/getLoadLiquidCommands' import { createFile, getLabwareDefinitionsInUse } from '../selectors' import { fileMetadata, @@ -29,6 +30,12 @@ import { } from '../../../../step-generation/src/types' import { LabwareDefByDefURI } from '../../labware-defs' +jest.mock('../../load-file/migration/utils/getLoadLiquidCommands') + +const mockGetLoadLiquidCommands = getLoadLiquidCommands as jest.MockedFunction< + typeof getLoadLiquidCommands +> + const getAjvValidator = (_protocolSchema: Record<string, any>) => { const ajv = new Ajv({ allErrors: true, @@ -57,6 +64,12 @@ const expectResultToMatchSchema = ( } describe('createFile selector', () => { + beforeEach(() => { + mockGetLoadLiquidCommands.mockReturnValue([]) + }) + afterEach(() => { + jest.restoreAllMocks() + }) it('should return a schema-valid JSON V6 protocol', () => { // @ts-expect-error(sa, 2021-6-15): resultFunc not part of Selector type const result = createFile.resultFunc( @@ -79,6 +92,10 @@ describe('createFile selector', () => { // have the opportunity to validate their part of the schema expect(!isEmpty(result.labware)).toBe(true) expect(!isEmpty(result.pipettes)).toBe(true) + expect(mockGetLoadLiquidCommands).toHaveBeenCalledWith( + ingredients, + ingredLocations + ) }) }) describe('getLabwareDefinitionsInUse util', () => { diff --git a/protocol-designer/src/file-data/selectors/fileCreator.ts b/protocol-designer/src/file-data/selectors/fileCreator.ts index 6ff946fe27c..389a17a4cfa 100644 --- a/protocol-designer/src/file-data/selectors/fileCreator.ts +++ b/protocol-designer/src/file-data/selectors/fileCreator.ts @@ -214,7 +214,10 @@ export const createFile: Selector<ProtocolFile> = createSelector( } ) - const loadLiquidCommands = getLoadLiquidCommands(designerApplication) + const loadLiquidCommands = getLoadLiquidCommands( + ingredients, + ingredLocations + ) const modules: ProtocolFile['modules'] = mapValues( moduleEntities, (moduleEntity: ModuleEntity, moduleId: string) => ({ diff --git a/protocol-designer/src/load-file/migration/6_0_0.ts b/protocol-designer/src/load-file/migration/6_0_0.ts index f16361ee123..179392a58f9 100644 --- a/protocol-designer/src/load-file/migration/6_0_0.ts +++ b/protocol-designer/src/load-file/migration/6_0_0.ts @@ -121,7 +121,10 @@ export const migrateFile = ( } ) - const loadLiquidCommands = getLoadLiquidCommands(designerApplication) + const loadLiquidCommands = getLoadLiquidCommands( + designerApplication?.data?.ingredients, + designerApplication?.data?.ingredLocations + ) const migratedV5Commands = migrateCommands(commands) const liquids: ProtocolFile['liquids'] = diff --git a/protocol-designer/src/load-file/migration/__tests__/6_0_0.test.ts b/protocol-designer/src/load-file/migration/__tests__/6_0_0.test.ts index 1a27d3b2c73..dc48519af45 100644 --- a/protocol-designer/src/load-file/migration/__tests__/6_0_0.test.ts +++ b/protocol-designer/src/load-file/migration/__tests__/6_0_0.test.ts @@ -1,16 +1,26 @@ import { migrateFile } from '../6_0_0' +import { getLoadLiquidCommands } from '../utils/getLoadLiquidCommands' import _oldProtocol from 'protocol-designer/fixtures/protocol/5/doItAllV5.json' -import _oldProtocolMultipleLiquids from 'protocol-designer/fixtures/protocol/5/multipleLiquids.json' -import type { ProtocolFile, ProtocolFileV5 } from '@opentrons/shared-data' +import type { ProtocolFileV5 } from '@opentrons/shared-data' const oldProtocol = (_oldProtocol as unknown) as ProtocolFileV5<any> +jest.mock('../utils/getLoadLiquidCommands') + +const mockGetLoadLiquidCommands = getLoadLiquidCommands as jest.MockedFunction< + typeof getLoadLiquidCommands +> + describe('v6 migration', () => { - let migratedFile = {} as ProtocolFile beforeEach(() => { - migratedFile = migrateFile(oldProtocol) + mockGetLoadLiquidCommands.mockReturnValue([]) + }) + afterEach(() => { + jest.restoreAllMocks() }) it('removes slot from modules and labware', () => { + const migratedFile = migrateFile(oldProtocol) + expect( oldProtocol.modules[ '0b419310-75c7-11ea-b42f-4b64e50f43e5:magneticModuleType' @@ -35,6 +45,7 @@ describe('v6 migration', () => { ).toBeUndefined() }) it('removes mount from pipettes', () => { + const migratedFile = migrateFile(oldProtocol) expect( oldProtocol.pipettes['0b3f2210-75c7-11ea-b42f-4b64e50f43e5'].mount ).toEqual('left') @@ -44,6 +55,7 @@ describe('v6 migration', () => { ).toBeUndefined() }) it('adds deckId to Robot', () => { + const migratedFile = migrateFile(oldProtocol) expect(oldProtocol.robot).toEqual({ model: 'OT-2 Standard' }) expect(migratedFile.robot).toEqual({ model: 'OT-2 Standard', @@ -51,10 +63,12 @@ describe('v6 migration', () => { }) }) it('adds a liquids key', () => { + const migratedFile = migrateFile(oldProtocol) const expectedLiquids = { '0': { displayName: 'Water', description: null } } expect(migratedFile.liquids).toEqual(expectedLiquids) }) it('creates loadModule commands', () => { + const migratedFile = migrateFile(oldProtocol) const expectedLoadModuleCommands = [ { key: expect.any(String), @@ -81,6 +95,7 @@ describe('v6 migration', () => { expect(loadModuleCommands).toEqual(expectedLoadModuleCommands) }) it('creates loadPipette commands', () => { + const migratedFile = migrateFile(oldProtocol) const expectedLoadPipetteCommands = [ { key: expect.any(String), @@ -97,6 +112,7 @@ describe('v6 migration', () => { expect(loadPipetteCommands).toEqual(expectedLoadPipetteCommands) }) it('creates loadLabware commands', () => { + const migratedFile = migrateFile(oldProtocol) const loadLabwareCommands = migratedFile.commands.filter( command => command.commandType === 'loadLabware' ) @@ -142,204 +158,14 @@ describe('v6 migration', () => { expect(loadLabwareCommands).toEqual(expectedLoadLabwareCommaands) }) it('creates loadLiquid commands', () => { - const expectedLoadLiquidCommands = [ - { - key: expect.any(String), - commandType: 'loadLiquid', - params: { - liquidId: '0', - labwareId: - '6114d3d0-b759-11ec-81e8-7fa12dc3e861:opentrons/opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap/1', // this is just taken from the fixture - volumeByWell: { - A1: 222, - B1: 222, - C1: 222, - D1: 222, - A2: 222, - B2: 222, - C2: 222, - D2: 222, - }, - }, - }, - { - key: expect.any(String), - commandType: 'loadLiquid', - params: { - liquidId: '1', - labwareId: - '6114d3d0-b759-11ec-81e8-7fa12dc3e861:opentrons/opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap/1', // this is just taken from the fixture - volumeByWell: { - A3: 333, - B3: 333, - C3: 333, - D3: 333, - A4: 333, - B4: 333, - C4: 333, - D4: 333, - }, - }, - }, - { - key: expect.any(String), - commandType: 'loadLiquid', - params: { - liquidId: '2', - labwareId: - '6114d3d0-b759-11ec-81e8-7fa12dc3e861:opentrons/opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap/1', // this is just taken from the fixture - volumeByWell: { - A5: 444, - B5: 444, - C5: 444, - D5: 444, - A6: 444, - B6: 444, - C6: 444, - D6: 444, - }, - }, - }, - { - key: expect.any(String), - commandType: 'loadLiquid', - params: { - liquidId: '0', - labwareId: - '64c66a20-b759-11ec-81e8-7fa12dc3e861:opentrons/usascientific_96_wellplate_2.4ml_deep/1', // this is just taken from the fixture - volumeByWell: { - A1: 555, - B1: 555, - C1: 555, - D1: 555, - E1: 555, - F1: 555, - G1: 555, - H1: 555, - A2: 555, - B2: 555, - C2: 555, - D2: 555, - E2: 555, - F2: 555, - G2: 555, - H2: 555, - A3: 555, - B3: 555, - C3: 555, - D3: 555, - E3: 555, - F3: 555, - G3: 555, - H3: 555, - }, - }, - }, - { - key: expect.any(String), - commandType: 'loadLiquid', - params: { - liquidId: '1', - labwareId: - '64c66a20-b759-11ec-81e8-7fa12dc3e861:opentrons/usascientific_96_wellplate_2.4ml_deep/1', // this is just taken from the fixture - volumeByWell: { - A4: 666, - B4: 666, - C4: 666, - D4: 666, - E4: 666, - F4: 666, - G4: 666, - H4: 666, - A5: 666, - B5: 666, - C5: 666, - D5: 666, - E5: 666, - F5: 666, - G5: 666, - H5: 666, - A6: 666, - B6: 666, - C6: 666, - D6: 666, - E6: 666, - F6: 666, - G6: 666, - H6: 666, - }, - }, - }, - { - key: expect.any(String), - commandType: 'loadLiquid', - params: { - liquidId: '2', - labwareId: - '64c66a20-b759-11ec-81e8-7fa12dc3e861:opentrons/usascientific_96_wellplate_2.4ml_deep/1', // this is just taken from the fixture - volumeByWell: { - A7: 777, - B7: 777, - C7: 777, - D7: 777, - E7: 777, - F7: 777, - G7: 777, - H7: 777, - A8: 777, - B8: 777, - C8: 777, - D8: 777, - E8: 777, - F8: 777, - G8: 777, - H8: 777, - A9: 777, - B9: 777, - C9: 777, - D9: 777, - E9: 777, - F9: 777, - G9: 777, - H9: 777, - A10: 777, - B10: 777, - C10: 777, - D10: 777, - E10: 777, - F10: 777, - G10: 777, - H10: 777, - A11: 777, - B11: 777, - C11: 777, - D11: 777, - E11: 777, - F11: 777, - G11: 777, - H11: 777, - A12: 777, - B12: 777, - C12: 777, - D12: 777, - E12: 777, - F12: 777, - G12: 777, - H12: 777, - }, - }, - }, - ] - - const migratedLiquidsFile = migrateFile(_oldProtocolMultipleLiquids as any) - const loadLiquidCommands = migratedLiquidsFile.commands.filter( - command => command.commandType === 'loadLiquid' - ) - expect(loadLiquidCommands).toEqual( - expect.arrayContaining(expectedLoadLiquidCommands) + migrateFile(oldProtocol) + expect(mockGetLoadLiquidCommands).toHaveBeenCalledWith( + _oldProtocol.designerApplication.data.ingredients, + _oldProtocol.designerApplication.data.ingredLocations ) }) it('replaces air gap commands with aspirate commands', () => { + const migratedFile = migrateFile(oldProtocol) const expectedConvertedAirgapCommands = [ { key: expect.any(String), // no key used to exist in v5 commands diff --git a/protocol-designer/src/load-file/migration/utils/__tests__/getLoadLiquidCommands.test.ts b/protocol-designer/src/load-file/migration/utils/__tests__/getLoadLiquidCommands.test.ts new file mode 100644 index 00000000000..226e61dca5f --- /dev/null +++ b/protocol-designer/src/load-file/migration/utils/__tests__/getLoadLiquidCommands.test.ts @@ -0,0 +1,206 @@ +import _multipleLiquidsProtocol from '../../../../../fixtures/protocol/5/multipleLiquids.json' +import { getLoadLiquidCommands } from '../getLoadLiquidCommands' +import type { ProtocolFileV5 } from '@opentrons/shared-data' +import type { DesignerApplicationData } from '../getLoadLiquidCommands' + +const multipleLiquidsProtocol = (_multipleLiquidsProtocol as unknown) as ProtocolFileV5<DesignerApplicationData> + +describe('getLoadLiquidCommands', () => { + it('creates loadLiquid commands', () => { + const expectedLoadLiquidCommands = [ + { + key: expect.any(String), + commandType: 'loadLiquid', + params: { + liquidId: '0', + labwareId: + '6114d3d0-b759-11ec-81e8-7fa12dc3e861:opentrons/opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap/1', // this is just taken from the fixture + volumeByWell: { + A1: 222, + B1: 222, + C1: 222, + D1: 222, + A2: 222, + B2: 222, + C2: 222, + D2: 222, + }, + }, + }, + { + key: expect.any(String), + commandType: 'loadLiquid', + params: { + liquidId: '1', + labwareId: + '6114d3d0-b759-11ec-81e8-7fa12dc3e861:opentrons/opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap/1', // this is just taken from the fixture + volumeByWell: { + A3: 333, + B3: 333, + C3: 333, + D3: 333, + A4: 333, + B4: 333, + C4: 333, + D4: 333, + }, + }, + }, + { + key: expect.any(String), + commandType: 'loadLiquid', + params: { + liquidId: '2', + labwareId: + '6114d3d0-b759-11ec-81e8-7fa12dc3e861:opentrons/opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap/1', // this is just taken from the fixture + volumeByWell: { + A5: 444, + B5: 444, + C5: 444, + D5: 444, + A6: 444, + B6: 444, + C6: 444, + D6: 444, + }, + }, + }, + { + key: expect.any(String), + commandType: 'loadLiquid', + params: { + liquidId: '0', + labwareId: + '64c66a20-b759-11ec-81e8-7fa12dc3e861:opentrons/usascientific_96_wellplate_2.4ml_deep/1', // this is just taken from the fixture + volumeByWell: { + A1: 555, + B1: 555, + C1: 555, + D1: 555, + E1: 555, + F1: 555, + G1: 555, + H1: 555, + A2: 555, + B2: 555, + C2: 555, + D2: 555, + E2: 555, + F2: 555, + G2: 555, + H2: 555, + A3: 555, + B3: 555, + C3: 555, + D3: 555, + E3: 555, + F3: 555, + G3: 555, + H3: 555, + }, + }, + }, + { + key: expect.any(String), + commandType: 'loadLiquid', + params: { + liquidId: '1', + labwareId: + '64c66a20-b759-11ec-81e8-7fa12dc3e861:opentrons/usascientific_96_wellplate_2.4ml_deep/1', // this is just taken from the fixture + volumeByWell: { + A4: 666, + B4: 666, + C4: 666, + D4: 666, + E4: 666, + F4: 666, + G4: 666, + H4: 666, + A5: 666, + B5: 666, + C5: 666, + D5: 666, + E5: 666, + F5: 666, + G5: 666, + H5: 666, + A6: 666, + B6: 666, + C6: 666, + D6: 666, + E6: 666, + F6: 666, + G6: 666, + H6: 666, + }, + }, + }, + { + key: expect.any(String), + commandType: 'loadLiquid', + params: { + liquidId: '2', + labwareId: + '64c66a20-b759-11ec-81e8-7fa12dc3e861:opentrons/usascientific_96_wellplate_2.4ml_deep/1', // this is just taken from the fixture + volumeByWell: { + A7: 777, + B7: 777, + C7: 777, + D7: 777, + E7: 777, + F7: 777, + G7: 777, + H7: 777, + A8: 777, + B8: 777, + C8: 777, + D8: 777, + E8: 777, + F8: 777, + G8: 777, + H8: 777, + A9: 777, + B9: 777, + C9: 777, + D9: 777, + E9: 777, + F9: 777, + G9: 777, + H9: 777, + A10: 777, + B10: 777, + C10: 777, + D10: 777, + E10: 777, + F10: 777, + G10: 777, + H10: 777, + A11: 777, + B11: 777, + C11: 777, + D11: 777, + E11: 777, + F11: 777, + G11: 777, + H11: 777, + A12: 777, + B12: 777, + C12: 777, + D12: 777, + E12: 777, + F12: 777, + G12: 777, + H12: 777, + }, + }, + }, + ] + const ingredients = + multipleLiquidsProtocol.designerApplication?.data?.ingredients + const ingredLocations = + multipleLiquidsProtocol.designerApplication?.data?.ingredLocations + expect(getLoadLiquidCommands(ingredients, ingredLocations)).toEqual( + expect.arrayContaining(expectedLoadLiquidCommands) + ) + }) +}) diff --git a/protocol-designer/src/load-file/migration/utils/getLoadLiquidCommands.ts b/protocol-designer/src/load-file/migration/utils/getLoadLiquidCommands.ts index 0b693adbb9e..fa87a12833e 100644 --- a/protocol-designer/src/load-file/migration/utils/getLoadLiquidCommands.ts +++ b/protocol-designer/src/load-file/migration/utils/getLoadLiquidCommands.ts @@ -1,6 +1,5 @@ import reduce from 'lodash/reduce' import { uuid } from '../../../utils' -import type { ProtocolFileV5 } from '@opentrons/shared-data' import type { LoadLiquidCreateCommand } from '@opentrons/shared-data/protocol/types/schemaV6/command/setup' export interface DesignerApplicationData { @@ -20,20 +19,18 @@ export interface DesignerApplicationData { } export const getLoadLiquidCommands = ( - designerApplication: ProtocolFileV5<DesignerApplicationData>['designerApplication'] + ingredients?: DesignerApplicationData['ingredients'], + ingredLocations?: DesignerApplicationData['ingredLocations'] ): LoadLiquidCreateCommand[] => { let loadLiquidCommands: LoadLiquidCreateCommand[] = [] let labwareIdsByLiquidId: { [liquidId: string]: string[] } = {} - if ( - designerApplication?.data?.ingredLocations != null && - designerApplication?.data?.ingredients != null - ) { - Object.keys(designerApplication?.data?.ingredients).forEach(liquidId => { - if (designerApplication?.data?.ingredLocations != null) { + if (ingredLocations != null && ingredients != null) { + Object.keys(ingredients).forEach(liquidId => { + if (ingredLocations != null) { for (const [labwareId, liquidsByWellName] of Object.entries( - designerApplication?.data?.ingredLocations + ingredLocations )) { Object.values(liquidsByWellName).forEach(volumeByLiquidId => { if (liquidId in volumeByLiquidId) { @@ -63,7 +60,7 @@ export const getLoadLiquidCommands = ( const commands: LoadLiquidCreateCommand[] = labwareIds.map( labwareId => { const volumeByWell = reduce( - designerApplication.data?.ingredLocations[labwareId], + ingredLocations[labwareId], (acc, volumesByLiquidId, wellName) => { if (liquidId in volumesByLiquidId) { return {