From 65756016953ef41032eaa7a00ef65fb3d034e00c Mon Sep 17 00:00:00 2001 From: Nick Diehl <47604184+ncdiehl11@users.noreply.github.com> Date: Tue, 28 Jan 2025 10:55:58 -0500 Subject: [PATCH 01/22] fix(protocol-designer): fix offdeck container border (#17362) fix offDeck container border to be 12px Closes RQA-3699 --- protocol-designer/src/pages/Designer/Offdeck/OffDeckDetails.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocol-designer/src/pages/Designer/Offdeck/OffDeckDetails.tsx b/protocol-designer/src/pages/Designer/Offdeck/OffDeckDetails.tsx index 05720f81555..5f219e8ecd1 100644 --- a/protocol-designer/src/pages/Designer/Offdeck/OffDeckDetails.tsx +++ b/protocol-designer/src/pages/Designer/Offdeck/OffDeckDetails.tsx @@ -68,7 +68,7 @@ export function OffDeckDetails(props: OffDeckDetailsProps): JSX.Element { return ( Date: Tue, 28 Jan 2025 11:43:04 -0500 Subject: [PATCH 02/22] feat(step-generation): introduce airGapInPlace command (#17357) closes AUTH-1365 introduce airGapInPlace command to be used whenever there is an aspirate command that is meant to be an air gap - meaning an aspirate air gap is now: moveToWell followed by airGapInPlace --- .../src/__tests__/consolidate.test.ts | 203 ++++++++++---- .../src/__tests__/distribute.test.ts | 125 +++++---- .../src/__tests__/transfer.test.ts | 261 +++++++++++------- .../commandCreators/atomic/airGapInPlace.ts | 37 +++ .../src/commandCreators/atomic/aspirate.ts | 2 - .../src/commandCreators/atomic/dispense.ts | 3 - .../src/commandCreators/atomic/index.ts | 6 +- .../commandCreators/compound/consolidate.ts | 22 +- .../commandCreators/compound/distribute.ts | 30 +- .../src/commandCreators/compound/transfer.ts | 16 +- .../src/fixtures/commandFixtures.ts | 31 ++- .../src/getNextRobotStateAndWarnings/index.ts | 1 + step-generation/src/utils/misc.ts | 34 +-- 13 files changed, 489 insertions(+), 282 deletions(-) create mode 100644 step-generation/src/commandCreators/atomic/airGapInPlace.ts diff --git a/step-generation/src/__tests__/consolidate.test.ts b/step-generation/src/__tests__/consolidate.test.ts index 9733fe5caa6..c77ab3ab53d 100644 --- a/step-generation/src/__tests__/consolidate.test.ts +++ b/step-generation/src/__tests__/consolidate.test.ts @@ -22,8 +22,8 @@ import { makeTouchTipHelper, pickUpTipHelper, SOURCE_LABWARE, - AIR_GAP_META, blowoutInPlaceHelper, + makeMoveToWellHelper, } from '../fixtures' import { DEST_WELL_BLOWOUT_DESTINATION } from '../utils' import type { @@ -33,16 +33,6 @@ import type { } from '@opentrons/shared-data' import type { ConsolidateArgs, InvariantContext, RobotState } from '../types' -const airGapHelper = makeAirGapHelper({ - wellLocation: { - origin: 'bottom', - offset: { - z: 11.54, - x: 0, - y: 0, - }, - }, -}) const aspirateHelper = makeAspirateHelper() const dispenseHelper = makeDispenseHelper() const touchTipHelper = makeTouchTipHelper() @@ -161,7 +151,8 @@ describe('consolidate single-channel', () => { aspirateHelper('A1', 50), aspirateHelper('A2', 50), dispenseHelper('B1', 100), - airGapHelper('B1', 5, { labwareId: 'destPlateId' }), + makeMoveToWellHelper('B1', DEST_LABWARE), + makeAirGapHelper(5), ]) }) @@ -852,24 +843,28 @@ describe('consolidate single-channel', () => { aspirateHelper('A1', 100), ...delayWithOffset('A1', SOURCE_LABWARE), - airGapHelper('A1', 5), + makeMoveToWellHelper('A1'), + makeAirGapHelper(5), delayCommand(12), aspirateHelper('A2', 100), ...delayWithOffset('A2', SOURCE_LABWARE), - airGapHelper('A2', 5), + makeMoveToWellHelper('A2'), + makeAirGapHelper(5), delayCommand(12), dispenseHelper('B1', 210), aspirateHelper('A3', 100), ...delayWithOffset('A3', SOURCE_LABWARE), - airGapHelper('A3', 5), + makeMoveToWellHelper('A3'), + makeAirGapHelper(5), delayCommand(12), aspirateHelper('A4', 100), ...delayWithOffset('A4', SOURCE_LABWARE), - airGapHelper('A4', 5), + makeMoveToWellHelper('A4'), + makeAirGapHelper(5), delayCommand(12), dispenseHelper('B1', 210), @@ -1010,18 +1005,22 @@ describe('consolidate single-channel', () => { pickUpTipHelper('A1'), aspirateHelper('A1', 100), - airGapHelper('A1', 5), + makeMoveToWellHelper('A1'), + makeAirGapHelper(5), aspirateHelper('A2', 100), - airGapHelper('A2', 5), + makeMoveToWellHelper('A2'), + makeAirGapHelper(5), dispenseHelper('B1', 210), aspirateHelper('A3', 100), - airGapHelper('A3', 5), + makeMoveToWellHelper('A3'), + makeAirGapHelper(5), aspirateHelper('A4', 100), - airGapHelper('A4', 5), + makeMoveToWellHelper('A4'), + makeAirGapHelper(5), dispenseHelper('B1', 210), ]) @@ -1044,22 +1043,26 @@ describe('consolidate single-channel', () => { pickUpTipHelper('A1'), aspirateHelper('A1', 150), - airGapHelper('A1', 5), + makeMoveToWellHelper('A1'), + makeAirGapHelper(5), dispenseHelper('B1', 155), aspirateHelper('A2', 150), - airGapHelper('A2', 5), + makeMoveToWellHelper('A2'), + makeAirGapHelper(5), dispenseHelper('B1', 155), aspirateHelper('A3', 150), - airGapHelper('A3', 5), + makeMoveToWellHelper('A3'), + makeAirGapHelper(5), dispenseHelper('B1', 155), aspirateHelper('A4', 150), - airGapHelper('A4', 5), + makeMoveToWellHelper('A4'), + makeAirGapHelper(5), dispenseHelper('B1', 155), ]) @@ -1213,12 +1216,10 @@ describe('consolidate single-channel', () => { }, // Air Gap: after aspirating from A1 { - commandType: 'aspirate', - meta: AIR_GAP_META, + commandType: 'moveToWell', key: expect.any(String), params: { pipetteId: 'p300SingleId', - volume: 31, labwareId: 'sourcePlateId', wellName: 'A1', wellLocation: { @@ -1229,6 +1230,14 @@ describe('consolidate single-channel', () => { z: 11.54, }, }, + }, + }, + { + commandType: 'airGapInPlace', + key: expect.any(String), + params: { + pipetteId: 'p300SingleId', + volume: 31, flowRate: 2.1, }, }, @@ -1300,12 +1309,10 @@ describe('consolidate single-channel', () => { }, // Aspirate > air gap: after aspirating from A2 { - commandType: 'aspirate', - meta: AIR_GAP_META, + commandType: 'moveToWell', key: expect.any(String), params: { pipetteId: 'p300SingleId', - volume: 31, labwareId: 'sourcePlateId', wellName: 'A2', wellLocation: { @@ -1316,6 +1323,14 @@ describe('consolidate single-channel', () => { z: 11.54, }, }, + }, + }, + { + commandType: 'airGapInPlace', + key: expect.any(String), + params: { + pipetteId: 'p300SingleId', + volume: 31, flowRate: 2.1, }, }, @@ -1560,12 +1575,10 @@ describe('consolidate single-channel', () => { }, // Aspirate > air gap: after aspirating from A3 { - commandType: 'aspirate', - meta: AIR_GAP_META, + commandType: 'moveToWell', key: expect.any(String), params: { pipetteId: 'p300SingleId', - volume: 31, labwareId: 'sourcePlateId', wellName: 'A3', wellLocation: { @@ -1576,6 +1589,14 @@ describe('consolidate single-channel', () => { z: 11.54, }, }, + }, + }, + { + commandType: 'airGapInPlace', + key: expect.any(String), + params: { + pipetteId: 'p300SingleId', + volume: 31, flowRate: 2.1, }, }, @@ -1703,14 +1724,12 @@ describe('consolidate single-channel', () => { }, // Dispense > air gap in dest well { - commandType: 'aspirate', - meta: AIR_GAP_META, + commandType: 'moveToWell', key: expect.any(String), params: { pipetteId: 'p300SingleId', labwareId: 'destPlateId', wellName: 'B1', - flowRate: 2.1, wellLocation: { origin: 'bottom', offset: { @@ -1719,7 +1738,15 @@ describe('consolidate single-channel', () => { z: 11.54, }, }, + }, + }, + { + commandType: 'airGapInPlace', + key: expect.any(String), + params: { + pipetteId: 'p300SingleId', volume: 35, + flowRate: 2.1, }, }, { @@ -1888,12 +1915,10 @@ describe('consolidate single-channel', () => { }, // Air Gap: after aspirating from A1 { - commandType: 'aspirate', - meta: AIR_GAP_META, + commandType: 'moveToWell', key: expect.any(String), params: { pipetteId: 'p300SingleId', - volume: 31, labwareId: 'sourcePlateId', wellName: 'A1', wellLocation: { @@ -1904,6 +1929,14 @@ describe('consolidate single-channel', () => { z: 11.54, }, }, + }, + }, + { + commandType: 'airGapInPlace', + key: expect.any(String), + params: { + pipetteId: 'p300SingleId', + volume: 31, flowRate: 2.1, }, }, @@ -1975,12 +2008,10 @@ describe('consolidate single-channel', () => { }, // Aspirate > air gap: after aspirating from A2 { - commandType: 'aspirate', - meta: AIR_GAP_META, + commandType: 'moveToWell', key: expect.any(String), params: { pipetteId: 'p300SingleId', - volume: 31, labwareId: 'sourcePlateId', wellName: 'A2', wellLocation: { @@ -1991,6 +2022,14 @@ describe('consolidate single-channel', () => { z: 11.54, }, }, + }, + }, + { + commandType: 'airGapInPlace', + key: expect.any(String), + params: { + pipetteId: 'p300SingleId', + volume: 31, flowRate: 2.1, }, }, @@ -2250,12 +2289,10 @@ describe('consolidate single-channel', () => { }, // Aspirate > air gap: after aspirating from A3 { - commandType: 'aspirate', - meta: AIR_GAP_META, + commandType: 'moveToWell', key: expect.any(String), params: { pipetteId: 'p300SingleId', - volume: 31, labwareId: 'sourcePlateId', wellName: 'A3', wellLocation: { @@ -2266,6 +2303,14 @@ describe('consolidate single-channel', () => { z: 11.54, }, }, + }, + }, + { + commandType: 'airGapInPlace', + key: expect.any(String), + params: { + pipetteId: 'p300SingleId', + volume: 31, flowRate: 2.1, }, }, @@ -2408,14 +2453,12 @@ describe('consolidate single-channel', () => { }, // Dispense > air gap in dest well { - commandType: 'aspirate', - meta: AIR_GAP_META, + commandType: 'moveToWell', key: expect.any(String), params: { pipetteId: 'p300SingleId', labwareId: 'destPlateId', wellName: 'B1', - flowRate: 2.1, wellLocation: { origin: 'bottom', offset: { @@ -2424,7 +2467,15 @@ describe('consolidate single-channel', () => { z: 11.54, }, }, + }, + }, + { + commandType: 'airGapInPlace', + key: expect.any(String), + params: { + pipetteId: 'p300SingleId', volume: 35, + flowRate: 2.1, }, }, { @@ -2590,12 +2641,10 @@ describe('consolidate single-channel', () => { }, // Air Gap: after aspirating from A1 { - commandType: 'aspirate', - meta: AIR_GAP_META, + commandType: 'moveToWell', key: expect.any(String), params: { pipetteId: 'p300SingleId', - volume: 31, labwareId: 'sourcePlateId', wellName: 'A1', wellLocation: { @@ -2606,6 +2655,14 @@ describe('consolidate single-channel', () => { z: 11.54, }, }, + }, + }, + { + commandType: 'airGapInPlace', + key: expect.any(String), + params: { + pipetteId: 'p300SingleId', + volume: 31, flowRate: 2.1, }, }, @@ -2677,12 +2734,10 @@ describe('consolidate single-channel', () => { }, // Aspirate > air gap: after aspirating from A2 { - commandType: 'aspirate', - meta: AIR_GAP_META, + commandType: 'moveToWell', key: expect.any(String), params: { pipetteId: 'p300SingleId', - volume: 31, labwareId: 'sourcePlateId', wellName: 'A2', wellLocation: { @@ -2693,6 +2748,14 @@ describe('consolidate single-channel', () => { z: 11.54, }, }, + }, + }, + { + commandType: 'airGapInPlace', + key: expect.any(String), + params: { + pipetteId: 'p300SingleId', + volume: 31, flowRate: 2.1, }, }, @@ -2836,8 +2899,7 @@ describe('consolidate single-channel', () => { // Change tip is "always" so we can Dispense > Air Gap here { - commandType: 'aspirate', - meta: AIR_GAP_META, + commandType: 'moveToWell', key: expect.any(String), params: { pipetteId: 'p300SingleId', @@ -2851,6 +2913,13 @@ describe('consolidate single-channel', () => { z: 11.54, }, }, + }, + }, + { + commandType: 'airGapInPlace', + key: expect.any(String), + params: { + pipetteId: 'p300SingleId', volume: 35, flowRate: 2.1, }, @@ -2989,12 +3058,10 @@ describe('consolidate single-channel', () => { }, // Aspirate > air gap: after aspirating from A3 { - commandType: 'aspirate', - meta: AIR_GAP_META, + commandType: 'moveToWell', key: expect.any(String), params: { pipetteId: 'p300SingleId', - volume: 31, labwareId: 'sourcePlateId', wellName: 'A3', wellLocation: { @@ -3005,6 +3072,14 @@ describe('consolidate single-channel', () => { z: 11.54, }, }, + }, + }, + { + commandType: 'airGapInPlace', + key: expect.any(String), + params: { + pipetteId: 'p300SingleId', + volume: 31, flowRate: 2.1, }, }, @@ -3147,8 +3222,7 @@ describe('consolidate single-channel', () => { }, // Dispense > air gap in dest well { - commandType: 'aspirate', - meta: AIR_GAP_META, + commandType: 'moveToWell', key: expect.any(String), params: { pipetteId: 'p300SingleId', @@ -3162,6 +3236,13 @@ describe('consolidate single-channel', () => { z: 11.54, }, }, + }, + }, + { + commandType: 'airGapInPlace', + key: expect.any(String), + params: { + pipetteId: 'p300SingleId', volume: 35, flowRate: 2.1, }, diff --git a/step-generation/src/__tests__/distribute.test.ts b/step-generation/src/__tests__/distribute.test.ts index b26b24e4d07..12f3676f09a 100644 --- a/step-generation/src/__tests__/distribute.test.ts +++ b/step-generation/src/__tests__/distribute.test.ts @@ -27,6 +27,7 @@ import { pickUpTipHelper, SOURCE_LABWARE, blowoutInPlaceHelper, + makeMoveToWellHelper, } from '../fixtures' import { distribute } from '../commandCreators/compound/distribute' import type { CreateCommand, LabwareDefinition2 } from '@opentrons/shared-data' @@ -36,17 +37,6 @@ import { DEST_WELL_BLOWOUT_DESTINATION, } from '../utils/misc' -// well depth for 96 plate is 10.54, so need to add 1mm to top of well -const airGapHelper = makeAirGapHelper({ - wellLocation: { - origin: 'bottom', - offset: { - x: 0, - y: 0, - z: 11.54, - }, - }, -}) const dispenseAirGapHelper = makeDispenseAirGapHelper({ wellLocation: { origin: 'bottom', @@ -457,8 +447,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', expect(res.commands).toEqual([ aspirateHelper('A1', 200), ...delayWithOffset('A1', SOURCE_LABWARE), - - airGapHelper('A1', 5), + makeMoveToWellHelper('A1'), + makeAirGapHelper(5), delayCommand(12), dispenseAirGapHelper('A2', 5), @@ -467,8 +457,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', aspirateHelper('A1', 200), ...delayWithOffset('A1', SOURCE_LABWARE), - - airGapHelper('A1', 5), + makeMoveToWellHelper('A1'), + makeAirGapHelper(5), delayCommand(12), dispenseAirGapHelper('A4', 5), dispenseHelper('A4', 100), @@ -496,13 +486,15 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', const res = getSuccessResult(result) expect(res.commands).toEqual([ aspirateHelper('A1', 200), - airGapHelper('A1', 5), + makeMoveToWellHelper('A1'), + makeAirGapHelper(5), dispenseAirGapHelper('A2', 5), dispenseHelper('A2', 100), dispenseHelper('A3', 100), aspirateHelper('A1', 200), - airGapHelper('A1', 5), + makeMoveToWellHelper('A1'), + makeAirGapHelper(5), dispenseAirGapHelper('A4', 5), dispenseHelper('A4', 100), dispenseHelper('A5', 100), @@ -530,7 +522,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', const res = getSuccessResult(result) expect(res.commands).toEqual([ aspirateHelper('A1', 200), - airGapHelper('A1', 5), + makeMoveToWellHelper('A1'), + makeAirGapHelper(5), dispenseAirGapHelper('A2', 5), delayCommand(12), @@ -540,7 +533,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', ...delayWithOffset('A3', DEST_LABWARE), aspirateHelper('A1', 200), - airGapHelper('A1', 5), + makeMoveToWellHelper('A1'), + makeAirGapHelper(5), dispenseAirGapHelper('A4', 5), delayCommand(12), @@ -930,7 +924,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', }, }), // aspirate > air gap - airGapHelper('A1', 31), + makeMoveToWellHelper('A1'), + makeAirGapHelper(31), delayCommand(11), // dispense #1 dispenseAirGapHelper('B1', 31), @@ -977,7 +972,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', }, }), // aspirate > air gap - airGapHelper('A1', 31), + makeMoveToWellHelper('A1'), + makeAirGapHelper(31), delayCommand(11), // dispense #1 dispenseAirGapHelper('A2', 31), @@ -1009,7 +1005,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', }, }), // aspirate > air gap - airGapHelper('A1', 31), + makeMoveToWellHelper('A1'), + makeAirGapHelper(31), delayCommand(11), dispenseAirGapHelper('A4', 31), delayCommand(12), @@ -1020,7 +1017,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', touchTipHelper('A4', { labwareId: DEST_LABWARE }), ...blowoutSingleToTrash, // use the dispense > air gap here before moving to trash - airGapHelper('A4', 3, { labwareId: DEST_LABWARE }), + makeMoveToWellHelper('A4', DEST_LABWARE), + makeAirGapHelper(3), delayCommand(11), // since we used dispense > air gap, drop the tip ...dropTipHelper(), @@ -1057,7 +1055,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', }, }), // aspirate > air gap - airGapHelper('A1', 31), + makeMoveToWellHelper('A1'), + makeAirGapHelper(31), delayCommand(11), // dispense #1 dispenseAirGapHelper('A2', 31), @@ -1073,7 +1072,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', touchTipHelper('A3', { labwareId: DEST_LABWARE }), ...blowoutSingleToTrash, // dispense > air gap since we are about to change the tip - airGapHelper('A3', 3, { labwareId: DEST_LABWARE }), // need to air gap here + makeMoveToWellHelper('A3', DEST_LABWARE), + makeAirGapHelper(3), delayCommand(11), // since we used dispense > air gap, drop the tip ...dropTipHelper(), @@ -1094,7 +1094,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', }, }), // aspirate > air gap - airGapHelper('A1', 31), + makeMoveToWellHelper('A1'), + makeAirGapHelper(31), delayCommand(11), // dispense #3 dispenseAirGapHelper('A4', 31), @@ -1105,7 +1106,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', touchTipHelper('A4', { labwareId: DEST_LABWARE }), ...blowoutSingleToTrash, // use the dispense > air gap here before moving to trash - airGapHelper('A4', 3, { labwareId: DEST_LABWARE }), + makeMoveToWellHelper('A4', DEST_LABWARE), + makeAirGapHelper(3), delayCommand(11), // since we used dispense > air gap, drop the tip // skip blowout into trash b/c we're about to drop tip anyway @@ -1143,7 +1145,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', }, }), // aspirate > air gap - airGapHelper('A1', 31), + makeMoveToWellHelper('A1'), + makeAirGapHelper(31), delayCommand(11), // dispense #1 dispenseAirGapHelper('A2', 31), @@ -1174,7 +1177,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', }, }), // aspirate > air gap - airGapHelper('A1', 31), + makeMoveToWellHelper('A1'), + makeAirGapHelper(31), delayCommand(11), // dispense #3 dispenseAirGapHelper('A4', 31), @@ -1185,7 +1189,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', touchTipHelper('A4', { labwareId: DEST_LABWARE }), ...blowoutSingleToTrash, // use the dispense > air gap here before moving to trash - airGapHelper('A4', 3, { labwareId: DEST_LABWARE }), + makeMoveToWellHelper('A4', DEST_LABWARE), + makeAirGapHelper(3), delayCommand(11), // since we used dispense > air gap, drop the tip ...dropTipHelper(), @@ -1220,7 +1225,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', }, }), // aspirate > air gap - airGapHelper('A1', 31), + makeMoveToWellHelper('A1'), + makeAirGapHelper(31), delayCommand(11), // dispense #1 dispenseAirGapHelper('A2', 31), @@ -1252,7 +1258,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', }, }), // aspirate > air gap - airGapHelper('A1', 31), + makeMoveToWellHelper('A1'), + makeAirGapHelper(31), delayCommand(11), // dispense #3 dispenseAirGapHelper('A4', 31), @@ -1265,7 +1272,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', blowoutSingleToSourceA1, // use the dispense > air gap here before moving to trash since it is the final dispense in the step // dispense > air gap from source since blowout location is source - airGapHelper('A1', 3), + makeMoveToWellHelper('A1'), + makeAirGapHelper(3), delayCommand(11), // since we used dispense > air gap, drop the tip ...dropTipHelper(), @@ -1302,7 +1310,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', }, }), // aspirate > air gap - airGapHelper('A1', 31), + makeMoveToWellHelper('A1'), + makeAirGapHelper(31), delayCommand(11), // dispense #1 dispenseAirGapHelper('A2', 31), @@ -1319,7 +1328,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', // blowout location is source so need to blowout blowoutSingleToSourceA1, // dispense > air gap so no liquid drops off the tip as pipette moves from source well to trash - airGapHelper('A1', 3), + makeMoveToWellHelper('A1'), + makeAirGapHelper(3), // delay after aspirating air delayCommand(11), // just drop the tip in the trash @@ -1341,7 +1351,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', }, }), // aspirate > air gap - airGapHelper('A1', 31), + makeMoveToWellHelper('A1'), + makeAirGapHelper(31), delayCommand(11), // dispense #3 dispenseAirGapHelper('A4', 31), @@ -1353,7 +1364,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', // blowout location is source so need to blowout blowoutSingleToSourceA1, // dispense > air gap so no liquid drops off the tip as pipette moves from source well to trash - airGapHelper('A1', 3), + makeMoveToWellHelper('A1'), + makeAirGapHelper(3), delayCommand(11), // since we used dispense > air gap, drop the tip ...dropTipHelper(), @@ -1390,7 +1402,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', }, }), // aspirate > air gap - airGapHelper('A1', 31), + makeMoveToWellHelper('A1'), + makeAirGapHelper(31), delayCommand(11), // dispense #1 dispenseAirGapHelper('A2', 31), @@ -1422,7 +1435,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', }, }), // aspirate > air gap - airGapHelper('A1', 31), + makeMoveToWellHelper('A1'), + makeAirGapHelper(31), delayCommand(11), // dispense #3 dispenseAirGapHelper('A4', 31), @@ -1434,7 +1448,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', // use the dispense > air gap here before moving to trash // since it is the final dispense in the step blowoutSingleToSourceA1, - airGapHelper('A1', 3), + makeMoveToWellHelper('A1'), + makeAirGapHelper(3), delayCommand(11), // since we used dispense > air gap, drop the tip ...dropTipHelper(), @@ -1469,7 +1484,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', }, }), // aspirate > air gap - airGapHelper('A1', 31), + makeMoveToWellHelper('A1'), + makeAirGapHelper(31), delayCommand(11), // dispense #1 dispenseAirGapHelper('A2', 31), @@ -1501,7 +1517,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', }, }), // aspirate > air gap - airGapHelper('A1', 31), + makeMoveToWellHelper('A1'), + makeAirGapHelper(31), delayCommand(11), // dispense #3 dispenseAirGapHelper('A4', 31), @@ -1514,7 +1531,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', blowoutSingleToDestA4, // use the dispense > air gap here before moving to trash // since it is the final dispense in the step - airGapHelper('A4', 3, { labwareId: DEST_LABWARE }), + makeMoveToWellHelper('A4', DEST_LABWARE), + makeAirGapHelper(3), delayCommand(11), // since we used dispense > air gap, drop the tip ...dropTipHelper(), @@ -1551,7 +1569,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', }, }), // aspirate > air gap - airGapHelper('A1', 31), + makeMoveToWellHelper('A1'), + makeAirGapHelper(31), delayCommand(11), // dispense #1 dispenseAirGapHelper('A2', 31), @@ -1568,7 +1587,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', // blowout location is dest so we gotta blowout blowoutSingleToDestA3, // dispense > air gap so no liquid drops off the tip as pipette moves from destination well to trash - airGapHelper('A3', 3, { labwareId: DEST_LABWARE }), + makeMoveToWellHelper('A3', DEST_LABWARE), + makeAirGapHelper(3), // dispense delay delayCommand(11), // just drop the tip in the trash @@ -1590,7 +1610,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', }, }), // aspirate > air gap - airGapHelper('A1', 31), + makeMoveToWellHelper('A1'), + makeAirGapHelper(31), delayCommand(11), // dispense #3 dispenseAirGapHelper('A4', 31), @@ -1602,7 +1623,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', // use the dispense > air gap here before moving to trash // since it is the final dispense in the step blowoutSingleToDestA4, - airGapHelper('A4', 3, { labwareId: DEST_LABWARE }), + makeMoveToWellHelper('A4', DEST_LABWARE), + makeAirGapHelper(3), delayCommand(11), // since we used dispense > air gap, drop the tip ...dropTipHelper(), @@ -1639,7 +1661,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', }, }), // aspirate > air gap - airGapHelper('A1', 31), + makeMoveToWellHelper('A1'), + makeAirGapHelper(31), delayCommand(11), // dispense #1 dispenseAirGapHelper('A2', 31), @@ -1671,7 +1694,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', }, }), // aspirate > air gap - airGapHelper('A1', 31), + makeMoveToWellHelper('A1'), + makeAirGapHelper(31), delayCommand(11), // dispense #3 dispenseAirGapHelper('A4', 31), @@ -1684,7 +1708,8 @@ describe('advanced settings: volume, mix, pre-wet tip, tip touch, tip position', blowoutSingleToDestA4, // use the dispense > air gap here before moving to trash // since it is the final dispense in the step - airGapHelper('A4', 3, { labwareId: DEST_LABWARE }), + makeMoveToWellHelper('A4', DEST_LABWARE), + makeAirGapHelper(3), delayCommand(11), // since we used dispense > air gap, drop the tip ...dropTipHelper(), diff --git a/step-generation/src/__tests__/transfer.test.ts b/step-generation/src/__tests__/transfer.test.ts index 72c89fc264a..cd22d6a321b 100644 --- a/step-generation/src/__tests__/transfer.test.ts +++ b/step-generation/src/__tests__/transfer.test.ts @@ -25,7 +25,7 @@ import { pickUpTipHelper, SOURCE_LABWARE, makeDispenseAirGapHelper, - AIR_GAP_META, + makeMoveToWellHelper, } from '../fixtures' import { FIXED_TRASH_ID } from '../constants' import { @@ -36,16 +36,6 @@ import { transfer } from '../commandCreators/compound/transfer' import type { LabwareDefinition2 } from '@opentrons/shared-data' import type { InvariantContext, RobotState, TransferArgs } from '../types' -const airGapHelper = makeAirGapHelper({ - wellLocation: { - origin: 'bottom', - offset: { - x: 0, - y: 0, - z: 11.54, - }, - }, -}) const dispenseAirGapHelper = makeDispenseAirGapHelper({ wellLocation: { origin: 'bottom', @@ -151,7 +141,8 @@ describe('pick up tip if no tip on pipette', () => { pickUpTipHelper('A1'), aspirateHelper('A1', 30), dispenseHelper('B2', 30), - airGapHelper('B2', 5, { labwareId: 'destPlateId' }), + makeMoveToWellHelper('B2', 'destPlateId'), + makeAirGapHelper(5), ]) }) @@ -843,11 +834,13 @@ describe('advanced options', () => { const res = getSuccessResult(result) expect(res.commands).toEqual([ aspirateHelper('A1', 295), - airGapHelper('A1', 5), + makeMoveToWellHelper('A1'), + makeAirGapHelper(5), dispenseAirGapHelper('B1', 5), dispenseHelper('B1', 295), aspirateHelper('A1', 55), - airGapHelper('A1', 5), + makeMoveToWellHelper('A1'), + makeAirGapHelper(5), dispenseAirGapHelper('B1', 5), dispenseHelper('B1', 55), ]) @@ -863,12 +856,13 @@ describe('advanced options', () => { const res = getSuccessResult(result) expect(res.commands).toEqual([ aspirateHelper('A1', 150), - airGapHelper('A1', 5), + makeMoveToWellHelper('A1'), + makeAirGapHelper(5), dispenseAirGapHelper('B1', 5), dispenseHelper('B1', 150), - aspirateHelper('A1', 150), - airGapHelper('A1', 5), + makeMoveToWellHelper('A1'), + makeAirGapHelper(5), dispenseAirGapHelper('B1', 5), dispenseHelper('B1', 150), ]) @@ -886,8 +880,8 @@ describe('advanced options', () => { expect(res.commands).toEqual([ aspirateHelper('A1', 295), ...delayWithOffset('A1', SOURCE_LABWARE), - - airGapHelper('A1', 5), + makeMoveToWellHelper('A1'), + makeAirGapHelper(5), delayCommand(12), dispenseAirGapHelper('B1', 5), @@ -895,8 +889,8 @@ describe('advanced options', () => { aspirateHelper('A1', 55), ...delayWithOffset('A1', SOURCE_LABWARE), - - airGapHelper('A1', 5), + makeMoveToWellHelper('A1'), + makeAirGapHelper(5), delayCommand(12), dispenseAirGapHelper('B1', 5), @@ -915,7 +909,8 @@ describe('advanced options', () => { const res = getSuccessResult(result) expect(res.commands).toEqual([ aspirateHelper('A1', 295), - airGapHelper('A1', 5), + makeMoveToWellHelper('A1'), + makeAirGapHelper(5), dispenseAirGapHelper('B1', 5), delayCommand(12), @@ -924,7 +919,8 @@ describe('advanced options', () => { ...delayWithOffset('B1', DEST_LABWARE), aspirateHelper('A1', 55), - airGapHelper('A1', 5), + makeMoveToWellHelper('A1'), + makeAirGapHelper(5), dispenseAirGapHelper('B1', 5), delayCommand(12), @@ -1288,12 +1284,10 @@ describe('advanced options', () => { }, // aspirate > air gap { - commandType: 'aspirate', - meta: AIR_GAP_META, + commandType: 'moveToWell', key: expect.any(String), params: { pipetteId: 'p300SingleId', - volume: 31, labwareId: 'sourcePlateId', wellName: 'A1', wellLocation: { @@ -1304,6 +1298,14 @@ describe('advanced options', () => { z: 11.54, }, }, + }, + }, + { + commandType: 'airGapInPlace', + key: expect.any(String), + params: { + pipetteId: 'p300SingleId', + volume: 31, flowRate: 2.1, }, }, @@ -1317,7 +1319,7 @@ describe('advanced options', () => { // dispense the aspirate > air gap { commandType: 'dispense', - meta: AIR_GAP_META, + key: expect.any(String), params: { pipetteId: 'p300SingleId', @@ -1592,12 +1594,10 @@ describe('advanced options', () => { }, // aspirate > air gap { - commandType: 'aspirate', - meta: AIR_GAP_META, + commandType: 'moveToWell', key: expect.any(String), params: { pipetteId: 'p300SingleId', - volume: 31, labwareId: 'sourcePlateId', wellName: 'A1', wellLocation: { @@ -1608,6 +1608,14 @@ describe('advanced options', () => { z: 11.54, }, }, + }, + }, + { + commandType: 'airGapInPlace', + key: expect.any(String), + params: { + pipetteId: 'p300SingleId', + volume: 31, flowRate: 2.1, }, }, @@ -1621,7 +1629,6 @@ describe('advanced options', () => { // dispense aspirate > air gap then liquid { commandType: 'dispense', - meta: AIR_GAP_META, key: expect.any(String), params: { pipetteId: 'p300SingleId', @@ -1777,22 +1784,28 @@ describe('advanced options', () => { }, // use the dispense > air gap here before moving to trash { - commandType: 'aspirate', - meta: AIR_GAP_META, + commandType: 'moveToWell', key: expect.any(String), params: { pipetteId: 'p300SingleId', - volume: 3, labwareId: 'destPlateId', wellName: 'B1', wellLocation: { origin: 'bottom', offset: { - z: 11.54, - y: 0, x: 0, + y: 0, + z: 11.54, }, }, + }, + }, + { + commandType: 'airGapInPlace', + key: expect.any(String), + params: { + pipetteId: 'p300SingleId', + volume: 3, flowRate: 2.1, }, }, @@ -1847,6 +1860,7 @@ describe('advanced options', () => { }, { commandType: 'dispense', + key: expect.any(String), params: { pipetteId: 'p300SingleId', @@ -1900,6 +1914,7 @@ describe('advanced options', () => { }, { commandType: 'dispense', + key: expect.any(String), params: { pipetteId: 'p300SingleId', @@ -1986,22 +2001,28 @@ describe('advanced options', () => { }, // aspirate > air gap { - commandType: 'aspirate', - meta: AIR_GAP_META, + commandType: 'moveToWell', key: expect.any(String), params: { pipetteId: 'p300SingleId', - volume: 31, labwareId: 'sourcePlateId', wellName: 'A1', wellLocation: { origin: 'bottom', offset: { - z: 11.54, - y: 0, x: 0, + y: 0, + z: 11.54, }, }, + }, + }, + { + commandType: 'airGapInPlace', + key: expect.any(String), + params: { + pipetteId: 'p300SingleId', + volume: 31, flowRate: 2.1, }, }, @@ -2015,7 +2036,6 @@ describe('advanced options', () => { // dispense the aspirate > air gap { commandType: 'dispense', - meta: AIR_GAP_META, key: expect.any(String), params: { pipetteId: 'p300SingleId', @@ -2288,23 +2308,29 @@ describe('advanced options', () => { }, // aspirate > air gap { - commandType: 'aspirate', - meta: AIR_GAP_META, + commandType: 'moveToWell', key: expect.any(String), params: { - flowRate: 2.1, + pipetteId: 'p300SingleId', labwareId: 'sourcePlateId', + wellName: 'A1', wellLocation: { origin: 'bottom', offset: { - z: 11.54, - y: 0, x: 0, + y: 0, + z: 11.54, }, }, + }, + }, + { + commandType: 'airGapInPlace', + key: expect.any(String), + params: { pipetteId: 'p300SingleId', volume: 31, - wellName: 'A1', + flowRate: 2.1, }, }, { @@ -2316,7 +2342,6 @@ describe('advanced options', () => { }, { commandType: 'dispense', - meta: AIR_GAP_META, key: expect.any(String), params: { flowRate: 2.2, @@ -2472,25 +2497,31 @@ describe('advanced options', () => { }, // dispense > air gap on the way to trash { - commandType: 'aspirate', - meta: AIR_GAP_META, + commandType: 'moveToWell', key: expect.any(String), params: { pipetteId: 'p300SingleId', labwareId: 'destPlateId', wellName: 'B1', - volume: 3, - flowRate: 2.1, wellLocation: { origin: 'bottom', offset: { - z: 11.54, - y: 0, x: 0, + y: 0, + z: 11.54, }, }, }, }, + { + commandType: 'airGapInPlace', + key: expect.any(String), + params: { + pipetteId: 'p300SingleId', + volume: 3, + flowRate: 2.1, + }, + }, { commandType: 'waitForDuration', key: expect.any(String), @@ -2710,22 +2741,28 @@ describe('advanced options', () => { }, // aspirate > air gap { - commandType: 'aspirate', - meta: AIR_GAP_META, + commandType: 'moveToWell', key: expect.any(String), params: { pipetteId: 'p300SingleId', - volume: 31, labwareId: 'sourcePlateId', wellName: 'A1', wellLocation: { origin: 'bottom', offset: { - z: 11.54, - y: 0, x: 0, + y: 0, + z: 11.54, }, }, + }, + }, + { + commandType: 'airGapInPlace', + key: expect.any(String), + params: { + pipetteId: 'p300SingleId', + volume: 31, flowRate: 2.1, }, }, @@ -2739,7 +2776,6 @@ describe('advanced options', () => { // dispense { commandType: 'dispense', - meta: AIR_GAP_META, key: expect.any(String), params: { pipetteId: 'p300SingleId', @@ -3012,22 +3048,28 @@ describe('advanced options', () => { }, // aspirate > air gap { - commandType: 'aspirate', - meta: AIR_GAP_META, + commandType: 'moveToWell', key: expect.any(String), params: { pipetteId: 'p300SingleId', - volume: 31, labwareId: 'sourcePlateId', wellName: 'A1', wellLocation: { origin: 'bottom', offset: { - z: 11.54, - y: 0, x: 0, + y: 0, + z: 11.54, }, }, + }, + }, + { + commandType: 'airGapInPlace', + key: expect.any(String), + params: { + pipetteId: 'p300SingleId', + volume: 31, flowRate: 2.1, }, }, @@ -3041,7 +3083,6 @@ describe('advanced options', () => { // dispense "aspirate > air gap" then dispense liquid { commandType: 'dispense', - meta: AIR_GAP_META, key: expect.any(String), params: { pipetteId: 'p300SingleId', @@ -3197,25 +3238,31 @@ describe('advanced options', () => { }, // dispense > air gap { - commandType: 'aspirate', - meta: AIR_GAP_META, + commandType: 'moveToWell', key: expect.any(String), params: { pipetteId: 'p300SingleId', labwareId: 'destPlateId', wellName: 'B1', - volume: 3, - flowRate: 2.1, wellLocation: { origin: 'bottom', offset: { - z: 11.54, - y: 0, x: 0, + y: 0, + z: 11.54, }, }, }, }, + { + commandType: 'airGapInPlace', + key: expect.any(String), + params: { + pipetteId: 'p300SingleId', + volume: 3, + flowRate: 2.1, + }, + }, { commandType: 'waitForDuration', key: expect.any(String), @@ -3433,22 +3480,28 @@ describe('advanced options', () => { }, // aspirate > air gap { - commandType: 'aspirate', - meta: AIR_GAP_META, + commandType: 'moveToWell', key: expect.any(String), params: { pipetteId: 'p300SingleId', - volume: 31, labwareId: 'sourcePlateId', wellName: 'A1', wellLocation: { origin: 'bottom', offset: { - z: 11.54, - y: 0, x: 0, + y: 0, + z: 11.54, }, }, + }, + }, + { + commandType: 'airGapInPlace', + key: expect.any(String), + params: { + pipetteId: 'p300SingleId', + volume: 31, flowRate: 2.1, }, }, @@ -3462,7 +3515,6 @@ describe('advanced options', () => { // dispense { commandType: 'dispense', - meta: AIR_GAP_META, key: expect.any(String), params: { pipetteId: 'p300SingleId', @@ -3618,23 +3670,29 @@ describe('advanced options', () => { }, // dispense > air gap { - commandType: 'aspirate', - meta: AIR_GAP_META, + commandType: 'moveToWell', key: expect.any(String), params: { pipetteId: 'p300SingleId', labwareId: 'sourcePlateId', wellName: 'A1', - flowRate: 2.1, wellLocation: { origin: 'bottom', offset: { - z: 11.54, - y: 0, x: 0, + y: 0, + z: 11.54, }, }, + }, + }, + { + commandType: 'airGapInPlace', + key: expect.any(String), + params: { + pipetteId: 'p300SingleId', volume: 3, + flowRate: 2.1, }, }, { @@ -3786,22 +3844,28 @@ describe('advanced options', () => { }, // aspirate > air gap { - commandType: 'aspirate', + commandType: 'moveToWell', key: expect.any(String), - meta: AIR_GAP_META, params: { pipetteId: 'p300SingleId', - volume: 31, labwareId: 'sourcePlateId', wellName: 'A1', wellLocation: { origin: 'bottom', offset: { - z: 11.54, - y: 0, x: 0, + y: 0, + z: 11.54, }, }, + }, + }, + { + commandType: 'airGapInPlace', + key: expect.any(String), + params: { + pipetteId: 'p300SingleId', + volume: 31, flowRate: 2.1, }, }, @@ -3815,7 +3879,6 @@ describe('advanced options', () => { // dispense "aspirate > air gap" then dispense liquid { commandType: 'dispense', - meta: AIR_GAP_META, key: expect.any(String), params: { pipetteId: 'p300SingleId', @@ -3971,25 +4034,31 @@ describe('advanced options', () => { }, // dispense > air gap { - commandType: 'aspirate', - meta: AIR_GAP_META, + commandType: 'moveToWell', key: expect.any(String), params: { pipetteId: 'p300SingleId', labwareId: 'sourcePlateId', wellName: 'A1', - volume: 3, - flowRate: 2.1, wellLocation: { origin: 'bottom', offset: { - z: 11.54, - y: 0, x: 0, + y: 0, + z: 11.54, }, }, }, }, + { + commandType: 'airGapInPlace', + key: expect.any(String), + params: { + pipetteId: 'p300SingleId', + volume: 3, + flowRate: 2.1, + }, + }, { commandType: 'waitForDuration', key: expect.any(String), diff --git a/step-generation/src/commandCreators/atomic/airGapInPlace.ts b/step-generation/src/commandCreators/atomic/airGapInPlace.ts new file mode 100644 index 00000000000..1a7656a3cda --- /dev/null +++ b/step-generation/src/commandCreators/atomic/airGapInPlace.ts @@ -0,0 +1,37 @@ +import { uuid } from '../../utils' +import { pipetteDoesNotExist } from '../../errorCreators' +import type { AirGapInPlaceParams } from '@opentrons/shared-data' +import type { CommandCreator, CommandCreatorError } from '../../types' + +export const airGapInPlace: CommandCreator = ( + args, + invariantContext, + prevRobotState +) => { + const { flowRate, pipetteId, volume } = args + const errors: CommandCreatorError[] = [] + const pipetteSpec = invariantContext.pipetteEntities[pipetteId]?.spec + + if (!pipetteSpec) { + errors.push( + pipetteDoesNotExist({ + pipette: pipetteId, + }) + ) + } + + const commands = [ + { + commandType: 'airGapInPlace' as const, + key: uuid(), + params: { + flowRate, + pipetteId, + volume, + }, + }, + ] + return { + commands, + } +} diff --git a/step-generation/src/commandCreators/atomic/aspirate.ts b/step-generation/src/commandCreators/atomic/aspirate.ts index 07b95f3459d..6d64cf00e7d 100644 --- a/step-generation/src/commandCreators/atomic/aspirate.ts +++ b/step-generation/src/commandCreators/atomic/aspirate.ts @@ -40,7 +40,6 @@ export const aspirate: CommandCreator = ( labwareId, wellName, flowRate, - isAirGap, tipRack, wellLocation, nozzles, @@ -257,7 +256,6 @@ export const aspirate: CommandCreator = ( wellLocation, flowRate, }, - ...(isAirGap && { meta: { isAirGap } }), }, ] return { diff --git a/step-generation/src/commandCreators/atomic/dispense.ts b/step-generation/src/commandCreators/atomic/dispense.ts index 554ebbce840..2ca1c737d08 100644 --- a/step-generation/src/commandCreators/atomic/dispense.ts +++ b/step-generation/src/commandCreators/atomic/dispense.ts @@ -26,7 +26,6 @@ import type { CommandCreator, CommandCreatorError } from '../../types' export interface DispenseAtomicCommandParams extends DispenseParams { nozzles: NozzleConfigurationStyle | null tipRack: string - isAirGap?: boolean } /** Dispense with given args. Requires tip. */ export const dispense: CommandCreator = ( @@ -40,7 +39,6 @@ export const dispense: CommandCreator = ( labwareId, wellName, flowRate, - isAirGap, wellLocation, nozzles, tipRack, @@ -226,7 +224,6 @@ export const dispense: CommandCreator = ( // pushOut will always be undefined in step-generation for now // since there is no easy way to allow users to for it in PD }, - ...(isAirGap && { meta: { isAirGap } }), }, ] return { diff --git a/step-generation/src/commandCreators/atomic/index.ts b/step-generation/src/commandCreators/atomic/index.ts index 5390c77d017..5e2dc2e7bf8 100644 --- a/step-generation/src/commandCreators/atomic/index.ts +++ b/step-generation/src/commandCreators/atomic/index.ts @@ -2,13 +2,14 @@ import { absorbanceReaderCloseLid } from './absorbanceReaderCloseLid' import { absorbanceReaderInitialize } from './absorbanceReaderInitialize' import { absorbanceReaderOpenLid } from './absorbanceReaderOpenLid' import { absorbanceReaderRead } from './absorbanceReaderRead' +import { airGapInPlace } from './airGapInPlace' import { aspirate } from './aspirate' import { aspirateInPlace } from './aspirateInPlace' import { blowout } from './blowout' import { blowOutInPlace } from './blowOutInPlace' +import { comment } from './comment' import { configureForVolume } from './configureForVolume' import { configureNozzleLayout } from './configureNozzleLayout' -import { comment } from './comment' import { deactivateTemperature } from './deactivateTemperature' import { delay } from './delay' import { disengageMagnet } from './disengageMagnet' @@ -21,12 +22,13 @@ import { moveLabware } from './moveLabware' import { moveToAddressableArea } from './moveToAddressableArea' import { moveToAddressableAreaForDropTip } from './moveToAddressableAreaForDropTip' import { moveToWell } from './moveToWell' +import { pickUpTip } from './pickUpTip' import { setTemperature } from './setTemperature' import { touchTip } from './touchTip' import { waitForTemperature } from './waitForTemperature' -import { pickUpTip } from './pickUpTip' export { + airGapInPlace, absorbanceReaderCloseLid, absorbanceReaderInitialize, absorbanceReaderOpenLid, diff --git a/step-generation/src/commandCreators/compound/consolidate.ts b/step-generation/src/commandCreators/compound/consolidate.ts index fb57d522f4d..579d3799161 100644 --- a/step-generation/src/commandCreators/compound/consolidate.ts +++ b/step-generation/src/commandCreators/compound/consolidate.ts @@ -2,11 +2,10 @@ import chunk from 'lodash/chunk' import flatMap from 'lodash/flatMap' import { COLUMN, - getWellDepth, LOW_VOLUME_PIPETTES, GRIPPER_WASTE_CHUTE_ADDRESSABLE_AREA, + getWellDepth, } from '@opentrons/shared-data' -import { AIR_GAP_OFFSET_FROM_TOP } from '../../constants' import * as errorCreators from '../../errorCreators' import { getPipetteWithTipMaxVol } from '../../robotStateSelectors' import { movableTrashCommandsUtil } from '../../utils/movableTrashCommandsUtil' @@ -15,15 +14,16 @@ import { curryCommandCreator, reduceCommandCreators, wasteChuteCommandsUtil, - getTrashOrLabware, airGapHelper, dispenseLocationHelper, moveHelper, getIsSafePipetteMovement, getWasteChuteAddressableAreaNamePip, getHasWasteChute, + getTrashOrLabware, } from '../../utils' import { + airGapInPlace, aspirate, configureForVolume, delay, @@ -39,6 +39,7 @@ import type { CommandCreator, CurriedCommandCreator, } from '../../types' +import { AIR_GAP_OFFSET_FROM_TOP } from '../../constants' export const consolidate: CommandCreator = ( args, @@ -178,7 +179,6 @@ export const consolidate: CommandCreator = ( ) const destinationWell = args.destWell - const destLabwareDef = trashOrLabware === 'labware' ? invariantContext.labwareEntities[args.destLabware].def @@ -221,12 +221,10 @@ export const consolidate: CommandCreator = ( getWellDepth(sourceLabwareDef, sourceWell) + AIR_GAP_OFFSET_FROM_TOP const airGapAfterAspirateCommands = aspirateAirGapVolume ? [ - curryCommandCreator(aspirate, { + curryCommandCreator(moveToWell, { pipetteId: args.pipette, - volume: aspirateAirGapVolume, labwareId: args.sourceLabware, wellName: sourceWell, - flowRate: aspirateFlowRateUlSec, wellLocation: { origin: 'bottom', offset: { @@ -235,9 +233,11 @@ export const consolidate: CommandCreator = ( y: 0, }, }, - isAirGap: true, - tipRack: args.tipRack, - nozzles, + }), + curryCommandCreator(airGapInPlace, { + pipetteId: args.pipette, + volume: aspirateAirGapVolume, + flowRate: aspirateFlowRateUlSec, }), ...(aspirateDelay != null ? [ @@ -467,8 +467,6 @@ export const consolidate: CommandCreator = ( destWell: destinationWell, flowRate: aspirateFlowRateUlSec, offsetFromBottomMm: airGapOffsetDestWell, - tipRack: args.tipRack, - nozzles, }), ...(aspirateDelay != null ? [ diff --git a/step-generation/src/commandCreators/compound/distribute.ts b/step-generation/src/commandCreators/compound/distribute.ts index d5f3e63c1cb..de87cffd29d 100644 --- a/step-generation/src/commandCreators/compound/distribute.ts +++ b/step-generation/src/commandCreators/compound/distribute.ts @@ -16,12 +16,13 @@ import { reduceCommandCreators, blowoutUtil, wasteChuteCommandsUtil, - getDispenseAirGapLocation, getIsSafePipetteMovement, getWasteChuteAddressableAreaNamePip, getHasWasteChute, + getDispenseAirGapLocation, } from '../../utils' import { + airGapInPlace, aspirate, configureForVolume, delay, @@ -215,12 +216,10 @@ export const distribute: CommandCreator = ( getWellDepth(destLabwareDef, firstDestWell) + AIR_GAP_OFFSET_FROM_TOP const airGapAfterAspirateCommands = aspirateAirGapVolume ? [ - curryCommandCreator(aspirate, { + curryCommandCreator(moveToWell, { pipetteId: args.pipette, - volume: aspirateAirGapVolume, labwareId: args.sourceLabware, wellName: args.sourceWell, - flowRate: aspirateFlowRateUlSec, wellLocation: { origin: 'bottom', offset: { @@ -229,9 +228,11 @@ export const distribute: CommandCreator = ( y: 0, }, }, - isAirGap: true, - tipRack: args.tipRack, - nozzles, + }), + curryCommandCreator(airGapInPlace, { + pipetteId: args.pipette, + volume: aspirateAirGapVolume, + flowRate: aspirateFlowRateUlSec, }), ...(aspirateDelay != null ? [ @@ -254,7 +255,6 @@ export const distribute: CommandCreator = ( y: 0, }, }, - isAirGap: true, nozzles, tipRack: args.tipRack, }), @@ -345,7 +345,6 @@ export const distribute: CommandCreator = ( }), ] } - const { dispenseAirGapLabware, dispenseAirGapWell, @@ -362,12 +361,10 @@ export const distribute: CommandCreator = ( const airGapAfterDispenseCommands = dispenseAirGapVolume && !willReuseTip ? [ - curryCommandCreator(aspirate, { + curryCommandCreator(moveToWell, { pipetteId: args.pipette, - volume: dispenseAirGapVolume, labwareId: dispenseAirGapLabware, wellName: dispenseAirGapWell, - flowRate: aspirateFlowRateUlSec, wellLocation: { origin: 'bottom', offset: { @@ -376,10 +373,11 @@ export const distribute: CommandCreator = ( y: 0, }, }, - isAirGap: true, - tipRack: args.tipRack, - - nozzles, + }), + curryCommandCreator(airGapInPlace, { + pipetteId: args.pipette, + volume: dispenseAirGapVolume, + flowRate: aspirateFlowRateUlSec, }), ...(aspirateDelay != null ? [ diff --git a/step-generation/src/commandCreators/compound/transfer.ts b/step-generation/src/commandCreators/compound/transfer.ts index cd62cbacfbc..adfb9c43887 100644 --- a/step-generation/src/commandCreators/compound/transfer.ts +++ b/step-generation/src/commandCreators/compound/transfer.ts @@ -22,6 +22,7 @@ import { getHasWasteChute, } from '../../utils' import { + airGapInPlace, aspirate, configureForVolume, delay, @@ -394,12 +395,10 @@ export const transfer: CommandCreator = ( const airGapAfterAspirateCommands = aspirateAirGapVolume && destinationWell != null ? [ - curryCommandCreator(aspirate, { + curryCommandCreator(moveToWell, { pipetteId: args.pipette, - volume: aspirateAirGapVolume, labwareId: args.sourceLabware, wellName: sourceWell, - flowRate: aspirateFlowRateUlSec, wellLocation: { origin: 'bottom', offset: { @@ -408,9 +407,11 @@ export const transfer: CommandCreator = ( y: 0, }, }, - isAirGap: true, - tipRack, - nozzles: args.nozzles, + }), + curryCommandCreator(airGapInPlace, { + pipetteId: args.pipette, + volume: aspirateAirGapVolume, + flowRate: aspirateFlowRateUlSec, }), ...(aspirateDelay != null ? [ @@ -433,7 +434,6 @@ export const transfer: CommandCreator = ( y: 0, }, }, - isAirGap: true, tipRack: args.tipRack, nozzles: args.nozzles, }), @@ -539,8 +539,6 @@ export const transfer: CommandCreator = ( destWell: destinationWell, flowRate: aspirateFlowRateUlSec, offsetFromBottomMm: airGapOffsetDestWell, - tipRack, - nozzles: args.nozzles, }), ...(aspirateDelay != null ? [ diff --git a/step-generation/src/fixtures/commandFixtures.ts b/step-generation/src/fixtures/commandFixtures.ts index 86b6e9ea030..aac4662fea0 100644 --- a/step-generation/src/fixtures/commandFixtures.ts +++ b/step-generation/src/fixtures/commandFixtures.ts @@ -3,7 +3,6 @@ import { tiprackWellNamesFlat, DEFAULT_PIPETTE, SOURCE_LABWARE, - AIR_GAP_META, DEFAULT_BLOWOUT_WELL, DEST_LABWARE, } from './data' @@ -139,21 +138,30 @@ export const makeAspirateHelper: MakeAspDispHelper = bakedP ...params, }, }) -export const makeAirGapHelper: MakeAirGapHelper = bakedParams => ( - wellName, - volume, - params -) => ({ - commandType: 'aspirate', - meta: AIR_GAP_META, +export const makeMoveToWellHelper = (wellName: string, labwareId?: string) => ({ + commandType: 'moveToWell', key: expect.any(String), params: { - ..._defaultAspirateParams, - ...bakedParams, + pipetteId: DEFAULT_PIPETTE, + labwareId: labwareId ?? SOURCE_LABWARE, wellName, + wellLocation: { + origin: 'bottom', + offset: { + x: 0, + y: 0, + z: 11.54, + }, + }, + }, +}) +export const makeAirGapHelper = (volume: number) => ({ + commandType: 'airGapInPlace', + key: expect.any(String), + params: { + pipetteId: DEFAULT_PIPETTE, volume, flowRate: ASPIRATE_FLOW_RATE, - ...params, }, }) export const blowoutHelper = ( @@ -238,7 +246,6 @@ export const makeDispenseAirGapHelper: MakeDispenseAirGapHelper = ( flowRate, offsetFromBottomMm, pipetteId, - tipRack, sourceId, sourceWell, volume, - nozzles, } = args const trashOrLabware = getTrashOrLabware( @@ -674,12 +670,10 @@ export const airGapHelper: CommandCreator = ( }) commands = [ - curryCommandCreator(aspirate, { - pipetteId: pipetteId, - volume, + curryCommandCreator(moveToWell, { + pipetteId, labwareId: dispenseAirGapLabware, wellName: dispenseAirGapWell, - flowRate, wellLocation: { origin: 'bottom', offset: { @@ -688,20 +682,20 @@ export const airGapHelper: CommandCreator = ( y: 0, }, }, - isAirGap: true, - tipRack, - nozzles, + }), + curryCommandCreator(airGapInPlace, { + pipetteId, + volume, + flowRate, }), ] // when aspirating out of multi wells for consolidate } else { commands = [ - curryCommandCreator(aspirate, { - pipetteId: pipetteId, - volume, + curryCommandCreator(moveToWell, { + pipetteId, labwareId: destinationId, wellName: destWell, - flowRate, wellLocation: { origin: 'bottom', offset: { @@ -710,9 +704,11 @@ export const airGapHelper: CommandCreator = ( y: 0, }, }, - isAirGap: true, - tipRack, - nozzles, + }), + curryCommandCreator(airGapInPlace, { + pipetteId, + volume, + flowRate, }), ] } From 02b70836f012c052d02b23c7cdbe1c5ed4c5e728 Mon Sep 17 00:00:00 2001 From: Nick Diehl <47604184+ncdiehl11@users.noreply.github.com> Date: Tue, 28 Jan 2025 12:06:24 -0500 Subject: [PATCH 03/22] fix(protocol-designer): add clear all liquids functionality (#17364) In liquids toolbox, the toolbox close button should be a button to clear all wells. On click, all wells of the labware should be cleared after confirming on a dialogue box. If no wells have liquid, the click no-ops, but the button remains enabled to reflect new design system. Closes RQA-3681 --- .../assets/localization/en/application.json | 1 + .../AssignLiquidsModal/LiquidToolbox.tsx | 31 ++++++++++++++++--- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/protocol-designer/src/assets/localization/en/application.json b/protocol-designer/src/assets/localization/en/application.json index b6d0505a0d1..256a2fa60db 100644 --- a/protocol-designer/src/assets/localization/en/application.json +++ b/protocol-designer/src/assets/localization/en/application.json @@ -1,5 +1,6 @@ { "are_you_sure": "Are you sure you want to remove liquids from all selected wells?", + "are_you_sure_clear_all_wells": "Are you sure you want to remove liquids from all wells?", "are_you_sure_delete_well": "Are you sure you want to delete well {{well}}?", "blowout": "Blowout", "cancel": "cancel", diff --git a/protocol-designer/src/organisms/AssignLiquidsModal/LiquidToolbox.tsx b/protocol-designer/src/organisms/AssignLiquidsModal/LiquidToolbox.tsx index 28c032f2373..1606e7a25da 100644 --- a/protocol-designer/src/organisms/AssignLiquidsModal/LiquidToolbox.tsx +++ b/protocol-designer/src/organisms/AssignLiquidsModal/LiquidToolbox.tsx @@ -89,6 +89,17 @@ export function LiquidToolbox(props: LiquidToolboxProps): JSX.Element { wellContentsSelectors.getAllWellContentsForActiveItem ) + const allWellsForActiveItem = + labwareId != null + ? Object.keys(allWellContentsForActiveItem?.[labwareId] ?? {}) + : [] + const activeItemHasLiquids = + labwareId != null + ? Object.values(allWellContentsForActiveItem?.[labwareId] ?? {}).some( + value => value.groupIds.length > 0 + ) + : false + const selectionHasLiquids = Boolean( labwareId != null && liquidLocations[labwareId] != null && @@ -143,6 +154,21 @@ export function LiquidToolbox(props: LiquidToolboxProps): JSX.Element { reset() } + const handleClearAllWells: () => void = () => { + if (labwareId != null && activeItemHasLiquids) { + if ( + global.confirm(t('application:are_you_sure_clear_all_wells') as string) + ) { + dispatch( + removeWellsContents({ + labwareId, + wells: allWellsForActiveItem, + }) + ) + } + } + } + const handleChangeVolume: (e: ChangeEvent) => void = e => { const value: string | null | undefined = e.currentTarget.value const masked = fieldProcessors.composeMaskers( @@ -247,7 +273,7 @@ export function LiquidToolbox(props: LiquidToolboxProps): JSX.Element { dispatch(deselectAllWells()) onClose() }} - onCloseClick={handleClearSelectedWells} + onCloseClick={handleClearAllWells} height="100%" width="21.875rem" closeButton={ @@ -255,9 +281,6 @@ export function LiquidToolbox(props: LiquidToolboxProps): JSX.Element { {t('clear_wells')} } - disableCloseButton={ - !(labwareId != null && selectedWells != null && selectionHasLiquids) - } > {(liquidsInLabware != null && liquidsInLabware.length > 0) || selectedWells.length > 0 ? ( From 9ffb69c59a397f2f7742d76ed4c3c4d197dfd954 Mon Sep 17 00:00:00 2001 From: Nick Diehl <47604184+ncdiehl11@users.noreply.github.com> Date: Tue, 28 Jan 2025 13:10:04 -0500 Subject: [PATCH 04/22] feat(protocol-designer): add announcement for 8.4.0 (#17365) Adds announcement and content for plate reader release in 8.4.0. Closes AUTH-1373 --- .../cypress/support/SupportModules.ts | 4 +- .../opentrons_absorbance_plate_reader.png | Bin 0 -> 836169 bytes .../src/assets/localization/en/modal.json | 10 ++ .../AnnouncementModal/announcements.tsx | 88 +++++++++++++++++- 4 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 protocol-designer/src/assets/images/opentrons_absorbance_plate_reader.png diff --git a/protocol-designer/cypress/support/SupportModules.ts b/protocol-designer/cypress/support/SupportModules.ts index 427b608d9ab..0fc0262a092 100644 --- a/protocol-designer/cypress/support/SupportModules.ts +++ b/protocol-designer/cypress/support/SupportModules.ts @@ -46,7 +46,7 @@ export const executeModSteps = (action: ModActions): void => { .click({ force: true }) break case ModActions.AddTemperatureStep: - cy.contains('button', 'Temperature').click() + cy.contains('button', 'Temperature').click({ force: true }) break case ModActions.ActivateTempdeck: cy.contains(ModContent.DecativeTempDeck) @@ -72,7 +72,7 @@ export const executeModSteps = (action: ModActions): void => { .click() break case ModActions.SaveButtonTempdeck: - cy.contains(ModContent.Save).click() + cy.contains(ModContent.Save).click({ force: true }) break default: throw new Error(`Unrecognized action: ${action as string}`) diff --git a/protocol-designer/src/assets/images/opentrons_absorbance_plate_reader.png b/protocol-designer/src/assets/images/opentrons_absorbance_plate_reader.png new file mode 100644 index 0000000000000000000000000000000000000000..5ac78216aa3ff55d1be53650bc4027971653f80f GIT binary patch literal 836169 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�HM_mKppE=`MQjWp4Nm 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�CNASx|L)9>`euN^@z}XCY-xzWPm=QiH&^ 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 kF{ zPm(%!?^i<;0gG16#sk@LPfPJPt|)qQdYb9p%_w$M!<7BAfb?CcE;>ZmT9*DZz8VUPS^zZUp#Ew35Gm`E>)bp>F5$u zX_Aut&;GXn0k;HfpF|ur!XqN$vkqY1M+zO9f-;a$<2G9cPjLreAh53_qx-O<@2QT) zOG`jaIsc2Yo}p|78I!EXU0n09R+bUSr8fWMLc59=Yidu%^^ zPX4ra1P3Ek{vJK_&_H0Xuh{d~FO{4%B(GQ(r+OThnfq(>q-OX;LWMAssz;3GaP#}@ zQYr+CJA83forp@S?P6vEx$pQA%=MCY>01=NFHHs%44C5x!pBQ%%I{fnRq(de;KPto zHQ+KZX8KrGHFST<*%CgMnNM87YCW+XX?_J)l<~-9{J>VFA_bpOAm;Bh$mv>}JG+P3 z1qiC5q{xk+A;~5);XQf>*5+UO<8(CuFkSzJ!H`#WsSs9E`9h*lW=Ae9X>KtTw}!72 z%K{4vA~MXnx>C5O91m+UT>wtgi$y9FshQq;ft;lRS*9!IU|B7*obP~b%^q=452NyG z=8#2@W)V0}cliqqqb;e0vIP0eXRXXBt~8ySqM2rK$)wLyvSs{#4#l)_=$az^6!jlg zBR*PVGUC+0+$WzP7fo1kTyV9Q^7|C;OeV8;v`s+Vw*y0zb}cCJIv?!^@6Hfgvwbo^ z5l5-;b#&t4N1a1avQMV&y45RXvd{-bML|VWa=)Sp_P0?Pj_TR8L|FGnTV6|drthr( zB=W~M(nGk>(f)&{eA&g<@vNtJi~D9E!B5fXWwx!xVoL(hGHFIiZk%-Ei=vilezkka z#F?q|;ccXe#v8=ra#DnLL@~aos#MVVh1Gyf_ z6zxCuw~#m+dM@Eq3(w?|8S=2hCwbi1_v#QATAEIS8 z*YgQ{7uW~yVwx`96#9NT&Fwy@B%YM}UM?P|n<2=u-9RgsywTI%odpSNR~$KQQuBKq zgArKbS<0UQuz2sgnXKbIPX|p+7XZ2@WL>Bt3j9v``-HC;7!MHEC8NQ>Df+VWlXy2Tc}A*8U6hV?<}-MiIEre*Lhm~R z`PY=5iatMuNa>2mSo|3A;ILSb?-PYoT5NL3NuDEdAvvypvdPod-2iF{xIW-v^f4C+ zWhI8gNZ7lvQ^S?RMLh(i9WzavP2X~W(jP$cS znR5JXff-iGW#HwKGSv{BfO>iV|4bPL}$q{!5Q6jOV6O`fG#Ca)81bEgp# z5V_4=?#;%sAnepAYBIA}S7KL6#4!4SR$tFzJR-oIHeS&eOtS7R*!?7FF%K}904J85JBS4Qp zgY?ve#Gki91IB2upu^3Tw>Y5gt?ACj5++VFE_f1JUG1OkgpK$7-Pg>zmVl`p^{>w) z^fP4a6pzd+=#;KF{+wbsf)aKmbjMEmLd2%79?|Ro|M3$u+C^lwpAJ0YR(d2~BH4ZK zFX)u*e}JD6-#tm1ACoVhB8@#GeVg*%4xjxMba1qzX!5m;eRSEb_lKc)8XsvYEPT_^ zze`kaC_SSkJ7P+pSW$o3N>U;8(ZgkQ$}#mXQo495F< zN+Htk5yFN18&$0Wz2~UGkB(vvE?B;xdOadmI^_PRZ`GmlMQIa@^(Sd6be2ogY0hMA ze`KhK8_Y13ndC3QF+`4syyxS}+&X(A@4LLi+a#Ur z;Avf1yli7;$A#_HPmN6cZPN+I zMH514fcQ+y$cn9r{Ej(pcuh>hyp_2_Oyb5g=0rbqH3klEij0Fvt$4mNCo63p*-2_; zGGfqZT7K(}Yt_R&V8}O|j*OX{fxN>}HJatOP0iHmpU9{ed6NDaYtI>MBEg%&vHMP5 z@-`pk=fIeX2k3V)Mx{A4}|oX@IlTjWk8b3@nA7wRaP^-IHggLX52x-v+d8=wJ5I;@Ls>nD>Dkt`~>^Bc#$ zOS1qtfbKVY3Dy7ytRgY}5viyf%Ra;fQ!o`^GMBS$@jEywLn{|ZUX0u+-sN=YP_JP# zSLtAvGB?!rwy9emBAXhG5BP!RA=g-08gvfA1llCZkTY4U#2-~G=8A;|%S%Ydu0i(_ zA4@kWReO%S`-tMm;dn}XGz&URvsf&{W0j$zp85~JP38B`sR~ZT=FilFT!j1n&f~J< zn>?JA#}8Qzv1f{Y7xCrVKRy$V&ai&yGyGuWrwpDDuNiCE+U!|taD_|vJ~S;d1xHSm zPI$EMZ-L?egI7e$heO-d=G1}t3`#^>sd^$9MJ zkq^PVTEh2pQ%v)Eb?B$i&sw7I(LV_{vl-B9&|6Gz$iL@_@RC<-iNo635o$por_nn} zOPVaw;+nW6#_CO%u3R~e*iapDb!alsh>%$TqDlqGVvF}8Tt_|?s0V-%bk^Eq*Kc7W zTKbbQ5=wHDBy`U|m4g1UMimRv0qK{WNpo945Div_{D@oTG2Fu4DB+;d*=EZti$+Rn zd?p8Sx0)zv*YY!MX=-NxrWi}CBEji6WaAIxpy?!YCNWzw_CR%Yeic8U`y+Y$hINEz zffWG*mH46Bp3AAKZY3rPB7G*P!2tmN@C+#sRJ~b(iBbIJ8qr1uU4r* zS9f}{t|mBw|q?t_-V?cS9Fw!!P`?%W%x68Qj16vF86`^6EvPB$Ure+T&} zCE#zt{bAhMAE|Mc%@-hWb`b@|0s5K0JUiFHrL+I*tzi-`emztyU{tm~>Mx5<&&K_N znYa95;+3{GjQc2p#WOYN$U;kbhDjs4{J@=B@|%lO_R=_smT5-Fdu0QiO4SWpuS{bb zxI~$_=RGdoQgzv0TY5vy)A!h4VzCOoFI#^a4nIUDLMu*_DF=W{WQpqz(>kzh1n3R7 z5AueE5IDU|2AXsw>^%_Uri=H6vKzEazamPhn{FCZ)VBOum6nRxNZrZz7DDtLR0URq zeNqW%Sc%0@dxSekj^B{}grdQcqcQ2)!H%Cut014^ZB>8SfvYm&7GOD1CrPh-sb-L# zN+(WSHep!fxQ1dHm%0POhTvr@;5}AepfZ{**-YfQ<}B#N!L$dl<0Wqc-XZ!>(fR*L zJ{tf^T-i8b_<4wSKPE^1g}LV)3rr-|O5Nic)zJlb3`U0ZD!W=WWoaZDBSU~|Rk-p| z5y(M@{>3oSrFMCrk<=E4f)&~~OGqDC`9QQk*M{RL>o@0(i9r9$vqp7N6@{ta?>~jS zS)%@DlD{B-rpNvq4yS+D|LobgSu18W{QI&&zfjcM&1=X1vSb=)`=D8Gje{7*6)FFg z`sl^KwXwWoh4m|C{#Qt#J>fq+d#^z5ev)1)e}5XpGX}N_);3(kP~iO;Q%G%A8OaVK z2F)NmsE~s9bxk9lqfhA|GD!=Q^ZMHrS=c}ai+is)uKU*?5x%(-W-lle-x}l8)?B-o z=du0gwYRkOx~N)WgKa3ekj-wdaY&4zXiN#mH23`ypBO-^IltwwM`gzpt-TvZ925vD ztNfatLU4$a-QH<7Oq;Sv#EFz$fea_zGZ1W6|L@D zn=bx+8xwR%=Q-T#x`J`FkMZXAs(mxC2(UOsNVp?Q66xM3Xh6A&!*yk3Fn6wbnA!Q zIq3@_HbQ(q8%IN%n?_6)JyHQq$EU%CGG=~U*0LQ1Bb;U^=;IP4cE!V2s#=UE;+ZKL z9X2mJ1RTp!L8ag0roe*X#(}lW(8+|}rg&0Q;xaCI9+T5FTa4G_iWaY4$fu?FUZU%VpImxnH$K*MhSVLH&)-7CMu5>anjlJn+xh%sY%+Y; z1%9_fmV#fl-p7@z&_Z{lq~CY%j?-J(xWe`-bZ3}D zW3<9i^xUNJDNA7u!0F6f+{zIFxzhGLs}1}X0GJ%M9nb)yaCAb3tT$1o@_kzb^eB6t zpB81ZD1vo*%Wl?kDl(RAapWNQ?2j+HvHK%do%+YQZjE|m!x>99`VR*^8ruWVNFn9k zDUUeDjWK?}j4(J2h;7qePQXEb0UOBvU(q07yYqzGVfOM4N};A7OLcRY#n<=jbQ%Ty z<`XsXWpX@TFqS);#}z?HGClTXYWx>Gga7-VNW|H@0cXR#evHaU4h9uS@}BkT#6CEw z*G#&qE7+-Ob)_xwB8}Jxmeo;s@>9&-i1vP|RvMdyNHC6_)N8kS4wyFt5W2~jlSXe7 zx*!`(TI_U>4rbNUl(OGGAOFn5rdSj>!ia?C96CCzD!c}!IqxFZ`gypAxHi~wScCvQ z`-n%MWEIb+0cUR8lA2@vQ;G95DNXWXRA2gA_&Y2nOveV+oQSrs))gxSX{=ucd-F*-i#}6pt1)WRxx2%dDGaM6Wt;|Urj~i< z+2jv1R|p++XOFoe_T*aQ`o`f7d9{TpZ5F~GfSmr-V5_OA)H62y#nMTDi6ujsn#DaF7 zh1}}Ye69VGVt-4aknc>Xn?P6=qM=Bh{soPnXF6JZAUtWd#k_J}1>ih>)`brZ<->{p zKZuGWSvNz%W>3R4(u$$Tf?jIGM-;Wr?+FE-`5$ z1_wtO>j|dZSZI79)??P=e7fXsws?UMuG4L?ihJq8wyGF2RI$mq6pAL*<#p9d=Q1=ggY)iS^; zJPEw0HAoZaZQF3cDh^@_Rr-niC*QljmAiZDkNG%9YzzsjP6sp?3&<55x*(w~U%m}xoUUIAlJSDdMjYH>U-Ah>i<8g!4Ett-gRrnd`yek_EL2^Z7N?|}@w>X#|4O_%kHc7P#fw~xr(oMK z`@rCg@0sd5f@56g7!4=A3|!>C?U6&iAa!C6iE_(;UlWa{d8rI z%-*ygioXHs0;o(K$`<0?h@khy9-;5} zK@ZF-s?%mOHrgCkz;iYmasKb=cXnn_klg0zC;IxQv_q-f=(~fS4*qdtrUqZ9W^FE5 zQhkQv*Am)*-0PKx>IrrDqErKP32etAb%Xf>FG#^Cu?_Te%!g@mkTv~M+lH0COE*vS(!DjfXZ0ZX(vW>huq%%NC7J63 zh%{{mQ^*|S;wRC4ahWu0Pk3VMT;!{;X@6(hraClNp)-$Tpt0DE|NXY5WZ`L=>kymX zVN59g81PH^@tGMyL1RsLVpp+=ML@bke;j%M6BH&t7;+JAPjHE`CEdLSIF*b@3%qsi zh+0mePlptpX{Kx%{vHtq;07QA?PLEOma(eq|7L!d;h1|KA)tn^Hs)BfYys4qv{TUA zdj7dCpIzHD&nW>4#zIawkZ-`kKX4sq29e4~E>p;}bwUtB$=Xzex5jd5u3fip>pjML2taW<*-P$__W^~rl2@P)c#{@K zIdgY0-4)3qUP85?74lD>9{+(MrcQfyQxScf*!5k$f4pS^4k0gusfj0AfOy`U=FhJ0 zmCWi8nIlHIiyN#&swnSLcHaK$>2=2EL@jyelLVxLH9VRWt6dHDT~~knNq^#Iebplu zT2<3OpNJYTcI}tH$yzDc>N#y2PVafZ~EA!`ylOyZS0P%Q1)v_ z)#xfaR`k)wSW}DgMWxokGHh-QHsxYGsaoD>Mn*)6?a&WR+u>}SW&bZL6!7JqiA4?8 zdx+LujGGZ1;_$EhAo;f+f0KugybD>`(DB9eF2yo7><@J}y=28~JJVZXVqfWk`o5VY zUKhjc1uq``;}Q34s>gp3 zlg6vfTuP6hMl3CZen3WS1D57-UR>65$eRdA5A2+caFJqi@B^#MJ2ATiBGOzXk9X>p zqgp1@ngitoi)b9+aA^bg#DZ&)KdWoXos}R6U1r%lO+{Y^WFG3nn+w~|?h8}BCS61c zj)(4~Fy;!GtcQ-~Xtk;55zQdsk>CZleg) z2)jksj6K%yIRX%{Yx%X?uiAVnsq5-u_#_Q8E7iamDJ)f!Ru`5A{UJg=X_8`t}}^nKEQc)BUe zM~Tim`(td0P^p0Tuy}^Sl6db&#W<^#STs!t8RG5wOwRV_!bormXtYp^7*prEie|Za zS|A;iL-uup)QRM)A9&dZ1DPw@Uh4*wrAr0CVWrFNnJg2siqGW=jeoMcPNXdGuTb85 zeqb#$5;Uapw3pw^K;E5lf2JQUW14-nS68qlUnI?l7dUrDJ~x{M%_z!|&auZ+9w^T&b<-&|1GfA3`Pq|w0n`1gO%fnmN7=y-<;-cf8x zkWS!t7;Mc$k3$F~@qnY8g9mOH>#HYDo2GS6{^owR!h@5XNbh<7)#!c=cFe0+;z^9% zYnMSW*<_r_s8_it$uql}a9l&Vx(kyXHE2m(^;^lX z83&@eDvhTzxKQ{)8H8dgo$5X4tY9kF9Fw((gGCZt_g$DVgh{?tU|aewpbk0ZyF!LX z#(b6=XY$+?V+7|ZhZ8?IoJk1miHDJeRvx+At+2ougt36z`Ax_ekEt+stwsKWofvD` zq^Vi@HGDpaXPoeSv7Zuff)>R}wvxo*3#+`xDOz)Dwm5J>hRjEXU=j36`*E8_Gic^5 zD~nO3&^9gQ)SA+YzdXI(z&lZE=&r=Rg>jv}@w8n^RYMdRLY;3D`TAwEL7P6A#J;hF zn1Oc~eiox;Rtp5Z@2=MGrE!}tfGb0OMA9&;`1_B>NQuN{(EUyQ!19SDX%In5y#Q87 zTk64YiRidb+e8>AARAE8QmdbXVBpEEobn9Co9?=6G;sRAcgL9>*_&MXY^z3N(Bqggt!YD|GC(DaBKYklp>@Qin_=jHEBq z+TN->H+llH6#+iVAAs}`n9Q{)k|TJq>6vtZe|DDeJ^Df15_Mgt#?WH zka9o@T6T~G@|Qj2y}!%|Xt7hg)MdIkz>C#wS_TFNeQSnfubHL!|A8y(kKsV{J`YTj zw?m3MJ!wGrHUuQQ=u?kJj!iI4x8fA|7G%b7V7IOHAwZhZEf2 z*&sPod_=s5h@LG`cX{u^$Mg7urfp`c97*ayC?*YNddp@#I^1v}y3`{ilLn zwR7$xWhYJeYuy>mh5nYFnd_dMNV?U=rWNgKmTqNy|F4W`k)Dl=4yt5~N9t=M*>NP> z(eZ?!Z!NT16L))cR3J1Zyt@PqbEUAC_1Rh^Ws9zBWSrXLCJm%ZDuE8BB7J(klM;n? zg7RUdBzfQNdrV+OB1WdI;s~L_NX#Xmo{Ua%&>6N?wn@E#0vx$`3#zb*|U-t6iXS}D?o9O@cLM!w^UiqlC( zma1o=CNHVkYtJeh$t(i%=DbcP|6`vX7rO9QTwn9L=wV95_{F&fhtaZ6$T;M3FvaT3 z1Lvm-rZnPbnGIz6n6+qD{b3P;jTKZs0Y)ZOM@TgL+u;i-1Lr6nXorO8;kzEB#eX7K z#>AXePEzT=SS$Vid^lRbXx_RjGZfR`y*2s!#W4=gL<+jmWe)D{jpeLAhjY#!b#<2! zK_M{e%pXiMaJ|UCwZtbFYXh0yL=KmxL-mF|#^ThKfG?cI_Cp@iDuk{bzl21QmizV4 zr#F^583#dmd`DpDFPX|% z66PLMF#oQ{Iy|XWQmPE40!4j$c2xl&lsvPj)DB|f9?egYuq-&lO?_N=?dK|`MPe7v z?f1p08#GgVWZ4|lBPpX3vo%PTO``}-t`ev;#J`Z5#C6d9 z+#L73C5QAU#OI=daRLxIkO+9cP)pYBoG9ZSt7RfMRoLU@9txAKIPZzLmP{0yZv54| zN|tDC__;qdg{bR!zWGjmEmC{;F}K|$>(#Gnpe2tLsdAw+B1eWy+F0?opvi&~q?J4a zJSL>`GhhJ6TKy*AD601sgM01I(e)YPuQsE<4+{a#Y^@cD=ny>IK`07Ad229f8*=&t zl$*6BQ)Y2!43u&(fL=eAK7hqG6z&iyL~1 zt&1JOM9aZ4>MH?{FT8OlFAfjaS22WiMH05-X6`waX&s&z$?rz*7z@=t{L8}B!q7_? ze-8pPdrPd&mBlGMSN$5c#1_ILPL@}z+LI!R07;JmW~9NsA>k8)Z)HnZ<;Ll!_}q_Ki#c8Y0mSxmBw*z1S~@C za7gw>=R5Nv#i9A^+;umouBRWC8jR|R-!I9LkD1M+bIu~Zjkr_WCo|^(QL|Z5S`fpC2cja}Ddpt*8e8${p zJ2ds7m);oK2pC7YS;2xmnbkc3HLVn@6Ua_%56qua=p~fsx6##LvtNV$IlgeyjU6Ey>oo7uArNluu7J_i%jxYzvZqgi~WA zduGsKySfcsq8NAs_Vm+Z3`+_BusBmSCh(Yi=O7 z>#ElXex9h?WWmtmIj|XwV@v5lT6%>ec7=hrSH0$t86t&Kkt8HbjK@F=2#Pd&oW2_@ z(h12u9Tyi@=S#6Y-hKP1;P7AD8;9YFcANuw2WOo%yFeOzINm}sJvR+ttTw#D!~pq| z>D*|bOyI1i()SWW!BPfr7-jL`=-dw-g(RS>9Gsb46qdmEQSEVfte!4eU`mZoPXVss)us$1zC$+4@b4q<>(07d!{Ns3T- zP>D&-1=%gwjKC5*xgkv*{7{Kq3}cMn^;VBa_9;73MMKuX;tRL-^Hjicu85e-kK{b< z8Ed4??Y{GZO8Te|TQdHFod|eaoamBu4_)_OqyZ*;yg{m(?!$;t$%?Ao21YhCK}qAd z5O_V@(2Rt>iaqhv+@@oTTx|%Os%;7<1yq}^hcoF3IqRM$CdcrM#w+us2wR;`4K_7d z{XspwEmGrt59Gx~MTX_z%mJc}pJiZljn*m&0vOuN>#D<3gpJ4y$)ipyXd|fdx1lG% zN9VmS(~pj=X9JmXUsI3c#AiQ+G2vd~27TDEKFqCuOVE$|>-S+9f~Rzqv)@_i`?N@< zCtjUx`D(Q!+yXlyR0qn#1h<*!a@|fX=aSkk47_E1nzAs_=15`jB8#v{q7>&kkwpdv zT$qhC2r_D+T~IXVr*d1&zgUw@cBQOw&i!B4$}m$YU*DcDropcUpef7jzs>xw*Ob2>uA$p+lr`p{so3 z?M=_;O0bmOY^)o&ir@hW&^6rq)!HlRBWm(SXvs)*-%sAl0g4>JU?%F^*#S8I;@V6lN$S=>>h&XKN?90#WqZ)FNI~E>)D5IT=cn(| z{8=bbfhi1e?Se%`=t;?i9-#RRW93H#B{;rn#}H-w2Uf|Z5j~iu;sOUsCvmOZX|%MR z@8ptIEoUX=f@HG52TPL@q9tx$h(!KpWogy{+qqUFF$v=k6$<;zCf8L zImfG@w|Wmyn77bZf`t`ZQs9kkV^V41#oGXSI^>`u)Y7KA9jh7G_-SN5)=DFa#}VOj z=u{N%v*h%ekH^rugFcLjHDy}wmOCTG7S59~8=KUmXQW$9cp#q=K*5*+HbWX&!k3G3 z)+&Uig5i4~tz2uJSdbqDDt@(aJZ4KI+*#FiUky>2;kPB zc{c#qpe7=hf&}Ek02+L~>rsC*(vrZLjQwPWwY>q-f+mfJm?*3-7Nj~e1`3W4gm3XH z84g^ym>mX@_gzkus~URdvTkXxuvKOKV4}`F6gRI)H4G)lSO`E3Mw-=n=LUV@InHgJ zH+?UL6r2){IlhFh1_wlwtCkhVsd3~r*!ZD+_WsEfbva2PGSyfVt3_KmybanQnG~?mi+o+NVUZsy!NdV9iG&8r0n0sskNdS zMKjx=kV(Rrcwj6?RSj_4-G{otz3mQBH=FNmhb$?jK<~w}|2dwi-^E?PjCFbj*gJ$~ z+Hrg@9e9(BVaeXs)5w#@BFeD+EANU(h>cnSXk4D44v!gbQ1{$X6}&QeQoh!Y>tgcC>R+g`J{+RUnKO~cBR3ijTmv~`MYmyy%!(6jCB<L`HWOCoFon=&zf_LZ7S=zXE~W#hpLJ z__#7LYz-6vZCN@AE`fc(XjyzZp?Hn+@$4OE-w%f5U!_7yK5@m7;YU{E)zX^p5+?2V z%Cx*2>2QFD5CJQlwyUY^NNGc-Mt5uxepsou!Ykpss{SnFiObazHnEs=6JC&(FF~tC zQgf-?JKw4Ud>5C`f*4KBy9g8COEGjIxcsRgirpG@P`*b*>_Y&haS2UnsOEe>iV(`9YVJi4>aOx1?mVz9_oZ`U(e~%vmImE z)tWM3Dl%T;Oy{=yKdM78z}@+?niQ!(Sc<)L#PnK0@-I^wdjCHYMN+<~Ge;M4xif@| zBF{`46tq;**&h7oeYt}F#Y-ql;gA zV>`k=wVF%DT<65^(CZTAFT}6YSSH$Y(CocKq*hZV%C2{0)pD)jFet5>`F%7Qi1?^7&T5SRivX4VIm4A zz_4>}Qwu8$KU*8*`WC4VEAKl2$J?Mj6z>`bf7trl4CWnc(Dwk%&;t7(_EgYe7NQf; z4x|0i2?!?uqTd;Vm_Gq({+gRr;No}2U*133$;m>*)*KmjI2!FN3ha^b46%3=?h1NP zF(v8lnS$_7P#Dk_ZaROgdZere=xi!u(OM{l0@`OEoyT$Q8G!3Lr%dKLW3|x6A9lQ#c<+_jn>m?4;$Nw90Kt?6b;GbOrQs)sC}*_B6;ZS*L~fo9c@}jbaB21+U);-Cg~m0Xav~& zT6D2arE+5FV0&addcco3PhJ6)OM2Iqz|dBeL?5v-+Nt$oH*b8`>UOAT0<+6E^XMvB z^ywk8LiFXh;(RmcaWu8hkK0OA*0o$+20B`C$K`*+ME9nn!6 zqB${GIUB*)orN1z%#~@2BRJGaPL0exc##13Ig*{XU+)?qi|JQ}c;5)6Z0_ZUD167$ zxK&*Xl9YtDB<*mwFR3g4ia|5{V5zWY?!ot&zh3cuWtzFVCWTDC7nbPz23m!uZT)O% zYI7e*5W|EsOYawi4{D1gZQ&?fDYTY*PQSV7QXzE!XO3k#`{pW($3vLZJN0FYrZ~TK zJsTshsKl1_K5YF$##J>Tf-HYPV?(@{<#$j@oIGbGP<+GsKgJK8r8T#7a_s({iG; z7&Ca|3~_^mbMTd!Bws@&myjHXq%3raTGR4kqOflP6Mhi#ZMZz$%`oyWst!!0#PC^p zshJ!5@nGE_9wY=4 z0pUli%6s?*jpO^MLao!aL7m_eGow4L()3tY4+BaXC{L#(Nu8V>47GD+!(UnNe7-h=$cD$a(!vj=J=dm{pE(Ce&%Fnb*R-t zD^@V|&~&F5!68BbYV2V4LuzIc*I(b41Vy*^{^*6BSMzE8)Qc&uS>&I0ujd~eVq${B zf-vh3Wp|e@HU2es0jjA6@(L1pZ-1c$w5)z&R71N@fk#RZcNvx@C{>3P83MkrzjqRG zb^el4eMDa;Q%v;A0k*1E9|El}yDS_Wc{CX+`vls3Zix8R+GSK|-DSjZrR>3XzTE8p zf0ZsG({GtCKdk+pK!No0&J6CksN2KnHUcC305>~ckYtTTTh@1of7@G#FPI+AEcmq| zmyOT`W*^92vU=DGFAVZ~%>Bf>vG(iheI1FI?6hVISkr__E0J+b#u}v}<;;K%`^LnO z=wpd)HEgWJ~N@{RBsh zbNkJ!{}}$=Bb(PkCFyuf9yOdA5u4!cLe853gmX2^WV0})d*YC9#bj4KkiDO6`9xX7j4axX2ukpi0ZGK!Fqi$u z*x+ZRIxWr8%j1Ls@iAmn9pse~8ptxg7%tHjHkY*P#rzT~_8ZSSOeDarPr`B?QiP>VRPS33u4H zeFK$jgR@V$!gVSc^m`LoU!L`1*4O$DR8%V9Dh|iSjydwhvuDma{)f@;df(2R$h9${ z?BXO#0;OpvhU0xwVx(hIuokOolyf_cjEn-KzdORxzwm8vwPoLadJOvYW6Dl$(MR-` zfWMOe>0(s;qn>}gh}m#VumfijnG4Lnuq*Wp)1eD>0Z6y@C<*(l_QUln8bz8n+dyqs zY+5pB>jTt5D-&Vg&aFD%SIyE-=I-w2tk_qVx2aQ)0#M`|amit{4!~-u0%#Cuh2-t= zahd>aRz1j?OQd{UWBvBt*@H*1u8NHaNT$>)6J`22)5>Y7iAS;)*FkZ?z87kcf)a_kEzM~PVVZ8g+2Zl*Od3ipjoT0Zeje!2KU${p0L6pi ziSd6iNtXG_T5%ZFV6#%J1;MXj)&t1jD+zkh#bcqbYR#8MtZDt^<@@}w>hp3){l!~3 z75FwvVaWJLQ5F@Jub>iIu=9mcZy$M;}A-B_t1=V zOLs|kNT>9Gbf=&DeV)C)-*B&M-7C&@9>;@8o>}GDk+2y|%;<)6Ge}3Y1v?=Jaj`?B zr&~U2PE5R?L9wg9!w{wcEa-b%Z&B$&V|#}SY{SDs`rDV+jjkyU80jVrh=npg+@SW% zq|UM4Xqw;yZVCMPWXJDzY+AWkB2J5et;AyUPnQGpn!Kf5#R+n)vnK1M8GlA}QcLqg zkHS>=+V>wYN6r2Yd=~P0j+jgk*U7#-7wfrL5A&(%x?a#VEuWI1jFkSHUaW_k zx}(J@tD>ES1|QAyNfdv~{Pms9ZD5(V;opw{Nrg2j)M+z7WIl~lY<M})*gsNHj zK6^IP{!!^f9@o%4QN2a+Pz)LwG6sJ-+Ww%D@rgLFtQ1mH$yE_|j=o6XXuC7h_eT#m zP3}>DL}o!xr}c3c0Jjw0aTa|j?KRk%6S?jh$*`(f3X)#cJ0WFz#4?v03Q9bVZ*X<1 zdy5u-vNb5c`bylZY3J_1N{8ypL$Mc`(srNQl33?{2p4AX^`3=Czz5~ypBV^b>q+^@Zj#_a}Q;l zC)K4S7Mzd#f1lsYImXT8Pq;9J-!VbZ77oe}_Gxc%$nB=Z)^z5~37_u_y=fN@J&2l1 zeFku(Rq7)IqYLCe=(0!;&cyguFCO?}1VU9bD&BpLeSfICyx_nSsWkh4mhIvRzO ztQsrX&oxWfk*JSxD$VeA)q*hFBEjS(|89|4wHA&`Jn>vUu^%c@q_`AH=OaQMMq9nh z*)m%cfg_Ur{1B`x8Cu3Rx>XuoB#RP8&D(oR+lr~^cBeQF70l}gsQae^OEt~LJd}G; zlk5-^<-x(DQa1Cax$HBe z<)FGuGz4v z*X{da*KkJ!x3|}3tK64U|3Va8s4Xs=H*_WJaSNN#GuMQRhRAu42tRn_mjwNHDe93* zib=1zQRXNdmQXZeTfa`&Lv7`BiIzMHr4x?wj!_DlN@D((`jJpTg1>4aiDTWkcispy1*8+34C*KafhNT}9b?e~{}ID;t-)E=H8|Sb)Nz&h=_J z`Se((+;(|^n@oSfY%SKG+h9&uMU~%wrdMc4B%QV%Q&VbnIrvq%wdw6GoAUhYv*XT= z#fmylw7nWTO+5}aw)mL052?c}uD#kzcCrY6_pbJoV^c6(H8q=O+);oiE2YMed-Dv1 zumY%ZZ(LKWNC`b^oftlNkPNp0^^t=iUDz<$1X~op7C((%^z74bb2j?6puzgVr{l8> zBil+otPaeC9J~JshJU|>tKuLFDja_CyX};AS+N@ZoQWB{ELS==OWzjc!xSOiR3Vos z+V2spgR9QaOro?KtqsahyN)p(*^-3(Z}%GsV!mf>{9FEiSNXS)ZJs={x5nDx`;gm3 ztj=#;x*vY0sOCM&>_Tj8>m1>BwkUGrQp~3#s6FaO{Rpnck@(`}jyx{C$-5X=>9pda zs0%c(SQ|&peJ;%;_QP(t1tb&d23_C%!lUio@sHTH)tmvSc%fKJuV|bTg`t#KhDgiL z-bsdk*8ax{c+Sk+NLr>YI!O>&bFLFzHP?^}geK#Vb4d3G?#-Y|dDIntAMwBeD$lP_ zPTx2nL-DSI@q$=yOmyqVzG6 zAOa_@CS^uN__gV)s@TG`-#d0zVB%kmH-*F_gUG@VJPvXbA&b9>LO!b`u~KOui;r;# z?T!>3cS>E8Ce!LS5k6O`?CkH_7u2c4PXvUb23s!f$xARsT8vzTcZ#lxaf_x$+t+OzOk#9iOo zb&L2sh_UwX!>)@sT2H_g`rpHj_7C}(|Hx$F^t~d_j<~@|o#pXBJ=#QRbc?~1xk_4+ z=9y+!`y!dOFHLX@DlbZine@vvp;DYL0>Pf4FBa-lgo=8o3RfsiJ8CWYa!CcW+$ z#ag8bKW9((DjS!>m~)ja1HU@k7G`y|duJrQ>6CVH`YfDql+YZ`KUFAARZ@`ALGZ_6%vBKs zi=*V$rd|i?z}bSa%T&kT|BHt$O3VI8^&D7K#5S-clLH3hLkmzv$H3p9+?Mv0h4{|g zYPyX63>L$-a%b*j9MEoFw^Bxq^nqpFml(vEKBF1ENo8M$lH21m)OPt^t^B?_5f*<# zv+_MaCeqv(atBn*3J}N*N`_5K<7d}tptFS$n@K>%s@F2P97|C&qzC_5fL26E16C&6 zpen=|$0>5KBS-{X6OvXzG|0&N1OJ#eR;RUMt6tX6ZEO_kWiezU-Q?gwlzN_GMoA(p z+K#9Q(CIKlGC0y9t|RUH5wUYH;Qa{>6{xVWKbeWr!#%>?AX`&sPEEmFNe>*X7|PVK zi?69fqeTsrN&C`Ym8z!|<)p30XegT#J5+=BJ1t51yKcU5C!L;v9^xMwjp}~-I7l=W z0N2*6bWa4t75%LBSHwNo9NbKo)T-++mH5%*V z?jru{b#+tJZn9x$IY*R0dFMch$j7Z7f2Zs18*D%;N>vdd`(;ftyX;r0Pcg(^bRJar zNkx!7OB)KMtHn-%zm17D(R3Zzo>@4lV^6oSO$LnK130+Md!ZKiO9D|(pY&skJQ1Cw zFK{<9{QFgpiXXdi8W+i#);lqIzoVDf4CPDJ{#n>LuCWJpwCBU(lDPj{AxImEU(9WD z*7)rdmh#C$g2}B2BWv`#kZ9r=VGH5H(Vn?~KXsETBP#%#1nZ?d?G2bYm`6h=g|JzsH3LcornrcFGz>lfRHQitR_RqInrr+Lf54R3-94id< zrYx0X-}5q)Zd6_U6|F&`p0^A&C3^Uoot1bC5bT%Zh^66I1m6_(*W)^{^dye{oWqtw zI5bJVHE^J-t;jZm6LoX{wKKkkB*Kg*Uc zSPe6b&v0$;_7^(a@a#YoP?QW0kn!Afjh7UDajb=|3R$dV0!pWjc`}=YRw&ce^+i%! zT3c3-adHc1K{J@W&@~_=wvKpVs9P^d)PzS)IxPd~Bc+--e*KFBF6oCJy!Hv9e!P0g zP0sJU_=h4XQFF+CS4EzIqoP;G2=l7Cx(&R0@H8^D;RSN9?!QeiEhuA}j#437XTI|V zS4E>W`O)`@BUKKvC2H!F8e%_16x;$5zbgQQabJpiF;jn?yy0+A+&zLr3g&bilQFF2 z@;YFTHtPuFhJ!snHdI~Y{<^)kO&tBL+b)f?D|g!rn&SQ;d_FE;OZuNuQSQZ~)(xmm zpQmHvdopOa158GUd_MF;mCu}0BS#%W5S$CCE-k%mHD(5KQES|M-DaGpS1(bXuxK-w|Y2`H4(aAow*T9^^zTDP%|8uFJ}K+fX%=ggyh4 z!;b%ymTo@}JcsTugoh3ezLG7wul76e%QEXeu(3k@5#vjecGK`rRjd^6UvbN!C%ud6QQ6hw6pU*s^MTf_Svtl`~pr=bC zwjwG~f!Nh?!BPO#yVc3sx09cRw2VcvGNR41~BO~ z!sybM0imBeGR^HHURK$5ECmm1kqv&!aMM>(7O`7Y>;`aQeYC@)XC71#Mvn<5?ygiG zj^jpUB-Z~drEV*9ciH*#^OkEbdn^0qhJb7)hDEl~a8%)@h6qv zwI$MrnhdXUr&4-81WxHfMf|G)nNx5L zlb>uju{sBTCi!@&{|0i7jyl}QO9YfmkMOYKCYtk1f`>8F|l>p1_# zd;ar&t8l5cfGfrD(CK<@ozcj($I?VB$_>u+F++e!luGSLa<#41LOp_Ms?W$p@S3Fc zog&pM0kHO1QTj_Uzwk;Q(qgCG(9V1LdK(z26KBmY8iG9m(2oa?1dEjHI7*usR|PEQ zj^k53cit4hs)>kx%_o@olrA$O?9#pMri)fZhj~1Iub6LFxrxoJGfd& zu`xnz8K~U6^GWi0STd#)SMnS8HB_HgAF~jJC*xg(o^~&vgn5O~z zAGE|`gQKGhx#AlvfOrU^wg9t`)jW16`2^8u!$bwg%i?bUJS}lDs1gphFohy1PL5zA z{&>kZ1%4{kI@h?q-?iXiEEXovWeI8FG;b6I&l#dfm@5`Y<}uCRHMOXmk7Tm~)Uc*F z29a7&ml)LVVf4GEu@?*v(bm57jB;wp6KQZbR}7VdKvAmo3hF7Y>OvFpTq3BKv}3-Z zRE8G%vAH^Tac|1v6CSbB!h67?+eY;Pm8u<5)Y#xKEP5stjkj;GKt_f@ePsxn4WbwF?U(_++Lj|;eG*j`H({%i2M=bQJjlShAH>@y68sPi8GEGpsHcgW)g z1{GvR_} zsc+k{K+B%J*EZm}t}vhOpz?);v7vZ(Hxa4~1^LzX>>4^$mJ7&738WAF{*G_;9W@SD z4XwgRI@FG>(RiwCbNg1t_`_UiaQ((xA0lO&@;XNP&vel)rI42|@|)33{u46t#Fw9Q zs_nic;XEiFNXeuYF4U9cUZ;0b)RcgkiXS6tnf@7?Xar;_r7+IdFoSreI$HfM2E6_| zCybwzT8Z6U^I%6@}OjIHIZLc?usEjGy(!F%G9_Wh)Dri zVl@W!GjG#v)c=#R9ypfQ6Vr!X%~fMccz<%3^9BR7wI}TB<9X@B#=Nm{K8AUD< z`L@#4otS{LA<(D$%UA7C*uL>Y#OOrhF3Gtp;c0tDztTj>lCvNhuMEna=mPDS_zW?T zHqSVB1gtC_Z!`2tJr}t-B$2Q_u0HvJ;(p$*I`tKy76s+6QYDfG& z93Q6A?nX)wRWphCj?bB-TfLDc0!;hQo`4&2iiLNvs6IlJLc5nRE?Uq|)8J>zVn%({ zs3)Oz^tsA5=^80Pp$xVQ^GzVfm}Lpwh>_M}Vs!fNkhYM=Q!|icf`ysR{Y79-qP0@< zdjQQiut^h>vxpAaR{X&Z1b_|#6$i69K_IEs^ zXd>gB>MM?VCPyp#2cCjANr_HJ{06Bd`v%NZ4qV4grj-mNZ;SN?$@kbqn5OsHHOsV- zZ|C##27D#wJ8j|I4*&1rd-zK1!5i5;y}eF`WPAfZmh6YdkaV%g&^Q|%!#V$XrxB9%hPkK%25^_ii&#`6a= zn)vJHX41tf;wzR1t8$%YegapYdh02EVwe_a(-(9rp<|+??wWFBVrvK!H)o-n_t|1D zdv87lr#Y8EiS;WMP8<3ol(W!*i@zURX1~%^<|NtxC{FkI4?x~wr4DIO5&`L^DM*qs@=X8?HH~9WC?xJGK*6)emF0DEwcH_`30*2_YwR8T-3PPY83$3GiIR2evc5^|f+Kwsp>O z#wdpx2xcD)Q`RJj9Pj0o$wXP}MhHmOY7lWNNzk^^fGBDMeqU#pv|l7MrqtLxg-fLv z#yR+GmaaWNyOz*0YObH|(ykr=S2(}4%Ab$5yOAu^J2=+QETpEu$^zMmdss9lZu6tKU%#X}qHLe5k~24`qu_0MVAJc=9WH~aN+ zj~ln-_#tt<>{xh)PV@`X*rO|fT4|UH1qM}#pK9{jDj#6Vv1ueWDazI(6kUW@X-%M85| z(FD{sb(OCpntwa5JR)dBaL06{rO!62pew&0<9Fsh>&6BEXX|U`eL`SStnz4dG>-b+GPkkowxpPL8#7Hucab73ZeLN*dLO?He{W)fFJ?UGK6a9ndBQM zFY~Z+8RB>(_kA8oVZSR924HDbU_u!uoJ1hX6f4iRIXXBRL?Hp(3aiXkP z^xSKB=}xB{+Y^3nS?zQF=z5i(6^~h|dT0`B$Y{^EUK*iJrDLzB&)hN7H?4ZHltcbOjtMalu`X1$rY!(TxGoQ}4Gp zV?6Pdf*Dje!Q?C(EYqSRR!X5@1Q1R9!RO^_>>dnl-D)`l0^rOGtr!e6KaQ9rbRD5gw1eVM(+Ki4h z>b>B0BrrMHMz$z%pUVkb=9NiM!CJyD|Y3atZs z)Aso8;nyqY@whl7myX@&I8NXu%z*)j{@+fw7gu8($ced{qV7;$=`abw%I+=6IPgh- zJn8HtHS!4u+e_fB`lb(dx__$FprmG0AGx)JFSZ876JGZff5Q+bbO}qLr&)?vPwZTx zLfMB#4p=1RVF+Hk0o71EQ36>@eGgF0L7`N{v= z86kz0G-7`nhvaP;yXM#P3mS>QS11cmF{?0#D@IE_NSx)I zmMtO7`}PLDB`$>@h;ZqCjK4c@D?Pn8jpPn+0~oOfk0$*xTS*?t@#CfY=eR%(g0mxxFI zSvQ?Ro%pCQ{Y6pkIJwl1t6#N7)HhfUBNAy(oyJ{}2~K!{#-engn1{NY!8(eOtm9OH z_HQH&uGZ*Qk~ExYl&H^oXJZfThENS{ z8Be^g19mtn6(knC`oz=`Xnx@DB<%E!6XJ=YI4S( z40%NbO5Hm;`iTtYlT9jOH+$Hb6RrRUu2hzl$I6s2h55c6iB8x@-XNm?T_CH++8z1j z{NO)l5t#pwogzXO;MOb|P`)I5THgg9iYm8PX|HZumeNS8iHMJ-3s)PsoLPGB;WX*7 zByv9a{FYS#bk1Q=vt3;>yG|p?gYccgqG&g2cw}=GrPKB2|Jq7?{Rer)KJP)+Do05* zrS;N*PPH|oBAe4sN)Ytl!V+#ADD%P+A_Eg)=0PmKX&oBKPZDJhnAqzOSbj(0QeTDp_K55Wtrnu3B46pejt}F4b5tH^&*1G5?|4V>+Oq z{-Bsrg%uRLDE{fFetN)&+c{Y`BBKt$i1zOCD*=ciad_R7#X(i{N^JFE|5tUB(c|h_ z`7NkPlp(StHK@K(dL@!@2&bCj2{wc2K4nMm?q%DH@H*#gr?lZReoIu za!KYFNTR$gUnt7#-M(;l+}9_oULx=O-=zOCwb}MEq>f-Nf+J5i5cFZE_oJJHlmZHBA1bxC z^bj5A`})nQAOSuEGLCRJD*ev`I1|q<2hRZu`&=P?A~n~Oo?Y#}WSfs=XUEvI;XF(x z9D6`*o7JvLsQTZ}ZwD4Dk8psY;^jbj@TgiE?2cCvI5{!{{C(%72@qXcuzEQoe~P87 zaM(O_QL}jh=D_@dhQR0QcD~c{S-()EA}QXR8PZO1+o3ce4i5rSGCY((`x#z*4o|%J z=cfJQKd_7N;=?oCzn)>2(#Ui+f4~5UoaFrGEG^_evK->FL_D!Dq!}zhFI_R)TZ6N+ zq!evdfRKY_pAb$ngUXCRRd}HSN&q-x>8~%Zk22It{ z;o8EN(b(qLOA?PP1f!$LpkjnO;o}7ET|Acdcni zny6J$P56iSV#$k%Y+plB;y$fqc`aN~>ucEe^y)Md$~z9kcP<8cd_G)raLH?L@ zw&}uT1(hMeg!Ib7;khgyHHwPsg=F`8f$7a`l9>RvQ+^nL;ZI)(DG2D+I;U75ohwp( z-PQ1?F2w$p2{u#!_Vn+

hvBZ?JlTbQUknrNnufuphWJoih&}x{V_H@@fZJq*Pk&KKq&BDHcMrSd)8?^4A6W) z-ukMa6FUmPA|;XY#)<#C^fD{nUu*TEO(^<6C>J&rPOQn;A<{|ZnA7iHFh3}t5mc7# z+^{Q+M5E=*Q7E&b7{;udrLFLgf1_fpgXLKBz`G6aAA%?k+RM zKAAIogTA^{Dq$}lq%RhR0`&-tOw8i^BjdcqQjdVLmjO!HVfZMl{lMBD3PI%pAFd=o zYo^i|D0vICiNYuG2HxrTUYlt)N4t+BDF`oes((Aw3F-XAG! zKv^*zT9f)&T8irUo4#d2=THWpk634x@Rh$xLkzd1XIXZiXxZh%-16BmknJ#g@0ME- zC~aoOm73;@>NIvOs=(!+j8Z-b6;MDSHHZodZR`MkO{hxo%7E< z>&IthR`nkl&c3;FP-80zr7AXUYRoh7s(dIQyM(rC+M{y*$v~5+N$vTAXm1iDN^aQ> z)(p6AmYd@Fe_9i{oQ2mQ^XI~z)$IF~4;km1-2qX5;n+7t9^-~Kc^rU!VKsJJ8%~=J zi2(fUU;*B0yrL2d!%h4=VWIKHXTelhTnwRC4(x4s>uXgr*ffTBLkI>}s4;)g7dJ`n zZ8R(KuIfubLAh(K@oi5iHJ@VRwjNaqK%%0>wD(5^yL+?#DGu473HR%R53Sw$s?C!!} zjF1~BnF$81pjgcgh|P>y$J*I?`x?KI)hw;N2~G&dnoTupP(cPKg(%a!*olsuyMt*c zoUv9(%lw~ifJfxyfG;o9x`ZT}doC#caI|HfagI*^FIlR#b69xX%OL|=e`<$&bv-Wy z0|c0KhN@A)GPk7U>$Jx89&q6Jq9P>N~i_-oM~GkPHNVz(Cbh~PF}b@YBa6o z;1Wp9;0(mrI4;A05H&TZaD0MI$w!EAJNR(g*=8Yto{x)0wPy80OUCXMOBgknu8rHy z2x|n3MA{Nd%&e5pYQpGI_f!jw1iHW46}m8*MexR?A# zb4c?zHzSRazn*)I61qv!bg~bt#V#&y7ao%hK7v zzx&G$UkZ_#ux6Jdj`_i9vFm@Wr0OxywZyQy2v(U(Dl{)s&ctVhZ<8!EnRTNFPx<)m zZ+^>+@ZacC^W$F0qM(XbF#7Z>?S#j~YkEj8GZr~cd67)i4scJw3L!L!Y2Xt%D4$={ zG5?KS#Mpx?nNJ-d@*g}0I4Ytb_8uiUuqzp(-BL}u{})yJC=;I}nhvlYE9?*yfHp^l zS+P%ml?t(!rs$d5{e0eBc|2iQLK4#DtRaG3w{)Pg8JUg-4Q9j$QIMz`nbgZ7D$BZl z8j~QJ0^)9J6jM*5j{d-!V8|iV98Bx=H)-Lt!eeN8=5%M9t1tdS<>edsiHqK_zjEG- zDE*xsrA}&6I}u4#1_2I!JC)L#173Ooh=S`9m&*BRR2+6|TwS@0CfenXgU4 zwI~$5As*zifkW_fh1y`wYxXk853;<=XYNBPdb>??I*?)=OdVA;ASSY(*t;*U*+8WO zyEdpH6O!mn(A!8EGm+?*?4z>pI+60%I{W1_rJ;D$u%}y^)(0b!ENtw)zuf_jo;Qv0 zHhf*|o{|!kia6WtHjLoints~1aA|94YPkhe59N1o{O9GzGD1^>gM@amZG7{tf$W{W z&-SH%yD3op{QO)Nf56U!0?~|drMb>lxg_hug476P%R00mH88pq;e+z2n@8Dy1H>#? z3a0ph(wa+;ZXwJeh!2b3d1D#uVsqGwnN!ZIkK4VSj!&4CRh0s|r!#hZIxow^`nkRG zQqF@$`^P>hM<7CIVTc~DMt$uOJ@M zC9h?@y7T80JjueU=yq=q9`qgkd@(IC72l4ch2WHX#{gz$RIPEqc+~-he^RyKo>dSN zSU%4FF7B=_>SmkX`Xd7l7q*rxDsdBa1os|cZM1YNpF0WK9(dAnKx$UzD_3s&KdoZZ zd3nw~5RTon))K9{*b6KAr@UgYw~!(2fBFr~dgZw-&LyPO!cFrbcM+SM=26vOfx5 zxUywzl9FZj4|A(!aM-4}&qnosIq0Gqt^>n2mzR*k^YCqWsTY@Ib zshFMYEB;Gxu)w2=AqMw9Qa8{4K70!`J*8ipo#w@`%ftMh+JCcv&9C{kt7?V6$zt4Uj9{+VMn+ML?t^2Hg{X1Fh z!pI%)dh6Hn3qfkRv+xwW)(7DUJ;LwY`G}2Qs{IT~rF!pFK{EsS@`vnLYf+Gc6YV=v z{TT4*ni(hysc#H@qm{Hb!@wfmTnGi`I($$}upqHwLC0HFfQLQCuA&6lRN|~rwvWAE zdFiu^qAncH{aL8O$}GGZxf{{63W)88OjSS&~c@#Bo#Z$T|;Gu9BjPha0yb32yUNQIy zgW9rTYyy~(V9y3Hm%mFE;FZNvL}IH`fs#9`Ut2yc;MK=-?kC=3)&%D*?KfM?;aolp z;@9z6R`VHfU!JN4C{5`u_1E^S7z;04nSWTNtw8YEcDgNAronc@PMNVfJS%q})KAZC ztW;{qvq*V}^Y^|TM4LujnZs(M>ClYr^5{z_U@)L}Utl*A6%}9fR3eB4d?hXmFi8E} zm+z0A!s8JvE#`}l9)+7voY6y72Rp!?E$tT=q$%;P(7 zisE4pbmt-!qBy`mCgMC&wm<9w@w&(sj63~1?`PG~A-_$VOWS0iS%=La_=H{OOoxE(N z^~*eAw$zElWW$af`LO7jqSi^3x0sRN&70HtB~XlR9r zFW<*b3F6rL4;Va3ng9xwKVvN2X{6Uu2A9hOj!Q(pGKf$GtwCN6nvUgo)u?lHleWRH zU^J{o+GwRC zN5s5+<~6!;8|-d8E&{6YJ+~psFFN&nan}8ju{k5`V1yZO=FEv9%aYY%o75n>6<6zn z6sfZugv0lZAEFdKrqeoVC;d<_x#vbYmN7zf_b4A#c?HGghUnI53S9GXbG2D9=_TW# zG)XlEu8H>M1h%F8QVNBQ%`){j$`iUh^y4Y*(#&Vsg?6HD^zsVA{BX=zHS|7=%%@Jo zUrXcJPH5dEm7BRs1-GS)tIqAv`|IZ=$iTRhoscO`py~p+iL}}=%Z#>~$pitP06SJs z?awLlUm4)1hE0SY6Y0PCh{v|42uo z+0*!@*tk&>Vz|2sy1+}Gd3H{J6<9OUV~SOHS)cY{qP`6$JCZw698eaYv-LLj$9S?8 zGzSKXA>JaX4&Ad&&R?A8*VBc-_L)2B_JaWT{2{Pf$+NnxZ-UVL$9%ih^|pUGAiH1k z#Tl}ub40q%w@K#&x8O?@VlfZN?fYA^e&c|I#I&Dd>Xy9C)E)ZyI)A40QIQ%oSIS-@ zktiLa|8)odJa$I~H^aP1bQFhseH zAM8yLq1~52lNR^|$1=Kg@1J{szZhCKf;pG6S;1A!iluB{GLrDs%)mt^-#B)(2R@;N zA*o%|x_Lw{nX*5uU>im-O zxiS0ap}|pMuTWSBBA)F~O{X_iIU)E6dMV|SZVA{2xhuCv|CGzjN}5V#;TyA_{58*k z|MtpQ{Ao&h)=@HM=Xhn2BY|RHbcMz$N6bQFg(MPU!W!~ja?f_7WyZTx&d(phYMNdv zf$~72r7(K++s%M%@Kb0LSIHaV<#4a6&Ch~OrfacJ`}y=^18x9Uj}yp;|J@`PDRlD9 zJvvP7T?3aGQg}~&#SK0Y(tuty@EHXC7UW#q@9SIV(#CgyB#{of2p#}+dZIMa*pTsz z^E$zEwF0}%r$K%rt9JIWqFrDxTa(veXYDUu)#_^uXIJI#r%bEEfap~3X=1|Od8TP@M8TtWKUqVsVQ1Yq6H71x? zxhdgn18KO)s4b_`r!u+Snd^TL6P0madY{c+2lU}=GTzGa;7<4WdJp(lt>>+$b4Rt# z?44nLveK!&`mPx|^xokFL9=olfwr)Xd?X8WBZ$(Xq+-$!OvWZms*sls7V#WZtj5ur z6tv6`h-8{iaBMv+R#3Hyiu|oO?iop1W_>W&XriA+W667?j91Q;C3bhEa`RE7P-?9oJ-Vc!aKYr(kPy1rR;yxoLgsJi{jo^AUcp+W+7|4tT8f3MtU+lI@xHV zR3$ghdeoph{s*1;<JSi+Q%Rr>cdLt>K-*#=IF z{T-D}gE*V^_$vAdQUS+JI_*?L%g@1;%Z;rytFtxBi9|_gAPs9J5@ylSQiS4guzTv& zc0FSX8t5cHhBM#}DT6!cTsCVUs{k}B>~gsH(fi0P4^|nHn|lhc^x?E+nWg5hy6`6z zPTPxMsW+rbJe=~dmVvA2q-C0207YXA#S=T5QCb``}g+UCwGQUQA&i5Pa1gX1YE*m1Ji$e zDQ%7)A)0oRqd{b>tccf~U%kl3*G^Sp24^=XyL{q3t6;W!!2hHKnVrHQFyB99g}qma zPg8d2hXdKPbQ1Xw#^kj&V7kt{2Qyz?@&TU(OjR6f1V-UoQ+xws=aWXMIaiee2 zYNeN|VsC2N05?EWU@PWlIJfF*gTwO0Ju$3oVc!Mar#*#~EnCq%c~Z3>;;K0C+;;Pj z=OeT+A{=Ts-d9!iFa{Pm$!^&dd^Y3I@+zoung6uJn@Y2QI=7&WhFFb%7?=}oF!POQ z92Nb~mHXxVgMLk2@^rq?`K;k1dq&HalZ6u6Y^umHh|63-?0aK!^0>4ZkD?-tD$v<^ zi5z%+w2xJ!2yeF10UnJj>ZEd73j9UbMpOMP%$i}Y*~b|r_s|_cO|_Hi7{2y zu*6}E_sl^+9*LFGer&>k|8)zhUl+t&VI(!OWg}!7q;V{vSIt0kdJtm!-X39g1;}tg z(_imC(;R!-VHj(dO4}sUfOe-skCif6P*V|Au>d2<|A>~}c9kgelU9czvMG7HN;SA` zGnUrh0|88D0~?BG#Wp*^c^09dAK|^8f*$BT_R*nyAE4O+#^d<3E!PwxgN5dr4;otO z&=NYaBF}1@+f*n{rO^H}1DkIqZbbgN8`-~8C?3DSu>&-kX>2w#%sWb+ zIgjF=M3KmOvPYTS+7#Wxb_o{iE09UrR&1siNhh$<_<*tmS!A!7=ViY;2=Ft_VRE*` z=>}s?-Q@8d{m)Y3mTc*)ll1K)_XRjpWC8D$N(Zc*5+-8wfv3@KnUoBy5&-KdBzGB> z*d}5e!jg$0FE&piL6lYSI|~wACP?!R8epcJ(((}0E^!Tw3Hm;_^oX7^GIa+K9h@H-N=cf zwBr3Jr#VYxAk8XNv|@60fIEi;JN;;ILA~wAHv{a|wpHiK)xPUQuzfFj>#JMPxr{JI z=ZvPf^IV0mX)wnq63^H-yUwQCESR>#6W}LUf|`qvZe7esFw~fg2mr>U5%Fy>zP50{*UL#^4{^s)pAxkVf8f zTKh-eyFK z4c(-TidT89I5sIzauc0&yh~FZM49+Vi{7M6Dm&TB(NDzP11&~`<-+mXpk@R}s|8Ly zwn|yFieLZKP3(Yd>tI%Y;K%*p>?9BB`ee;8roA6lMJ-vHY$#5N1ad=JDpIt2Src?d zW$9mv_V!RY$7az*^{w2wMS2(z8F4H6lA7Mz#Bauw!6gyN2KLH_gkuta#yf!U=qfFy z2d>OTW&id6ne5m;us+4@et7xXAupTh%(gO)H1Fz!tR^sK0X%#|b8I;QB$h_;pUWzi z@S1R}6|l>chAMN;vzxP{L12j`IE$7Qv8~oR$z!RD?TRvg2Cp%5W|)H!eMhs#@Qbq{ zrGg6s3f%eyI}t2L6h2R40nmS-M_Y|T`WRx! z)pAZL*E}+R%N+%Hr~kjw5{nu5omw(e>Jsu>?FMuEftGPWVfbo zrUvo_q+cYxD0{v>y1w=mUP#RSVsiV^dQ$d)BYM5K707988QqviKUu>U|9n@jb$p*41Cts)!~q|)2{=rfwCY-<(Q z0`@fkhkRaPsz_oMus$-B0wAI7DMRSc$6!XtNKwQ4UZTGL(<&NZH_$JnuAP!(u<(Nb ze!*S@fjL?+ETvy74N`=_A{0v-{dN4SxKU`1lpy{q%K4{yE!$A0zq;~WP58BvL21OP z&%4!~^7mb;n*j~JdtGgjNNe*)hCZW4iYoG^B7Cb+A%Rn!quIv=RLswesMa_~?JC7o z{Q5IWNo=iHMd6W1`wYy=T!Yy+78-OF@VRJg1x<$Rh9ehvuA4A~O zmZIPV*%Nn^OemWgQ^Vl_BUwO*ZcWF{V}oQV2O?^}Im^)^7;gbsoc<)>7H85$*;)Vt zE=&63k+?;j%h~38cKx-=*8D7`o)G2i1G8SQYWp znJdIfo8R}fE2;T` z?wU9FXnX$YIS4R=A9D`fxS57Y`GgvM}?)VmowsWR(g;gL2#SYNIvRC z{qvyN$NZuh6`e~XV@s_q6V3b9vfx2UU<4OcG^F39Q}>^-LI|wDK@8BQ@kRRBuYxI@;C$` zQ#O!>{*d^=5>K8B_WK%#io3sW%<<(H@%Z%RRYA5B#FD>cjGI1pcYySAwMx*|x^~ti z?|p@Fkr(1WSyRP+$fHJl8PS^2=omSe9<(Y+&^)rdiqeMT|B^A?Q#f6^rBQC8BX|QTPmT?uW$x-)2b5=kmJcU}3W}hW(F8Tfl8a z^RjqT&z~k@m%iL)GJEKj0QpU$Xu{vz70O$A{vP4~kEnNGj05V{w%gcFVa9T4( z?k+Oee6*bwmPR*wxvm%%$jXL!9J{Y^QBmqWRL;naSJE(NmJM?qGAO0Ql+6eg3&<}s zq}EoIQ>CWAx$s63D+%4+(UA{FOIPxwZIgCRbmek@$FoXTXBT{WR)Ne$}5{HO$a1z#`khXfV=44b#xZkE_NpbOw5 zP)n<8E%aa~qll z9#9l4za;VNEZ zTK@!L{OLi~=@<4}7~U4Lc!)FtX4`}QzwxDI492MgB%)K1ENSA(E7WApW%dP>p?oB! zwI+WwtN!(!BR60Uqu!NaARr8Ui%U;o1Q}k>(^E!#6%ot!V^4y53an1d>eM^94xdQe zLm)SV&-5N7qcjJAT7ter1e05`W}<$lG3du*KUteyeLgsaU!roV#-j=mZTN@!Wrze+ zaAqP_MP}&QCPbO$={uLRmAj`SjelCC-Bq#i&HaY@<$b*Q8`~L=`<=g7v`-e<@FU2; zLW$f^Z))gg!1%7<&B;c2@?Kgcic{;^5^J6as_#DMBnujK2VRHhGy|BebP}twr~<|- z>^7xv*q^|PD+Y3e!G=9#BUNbNc$-i^^~J8_L4l_6WIZir+DD&N*!@2Z1NLJm7c|SS zezz>Wz85b`O8O6Es^T%V-kh-teptxUT+*V#+4ft4^FJOp#|h4>(U;f4;Wa~PDTGyO zCvg03Mc}qy_!b_m6g9GY$~M|{z-jp4SVh6K+#Ws*bAf`}JD!5coIkDUhi5rF>jc-y zJ4W}jl9N{zW?)!`_#e+f7Bhl2V81Zzya5iJ9JAp zOi+FSKxg9A!ad&x;~4|+fqRqJN{Z?JH5$@1%pr~Ic_Ax#EI3NY49=Q1pfT%IH=xLD z7&Go1I+WLd`0S0|XK@y2#00PdgP4dE=tz6jT7q>d`bv-;Jc>^8yZ_@p+g=j{Z^^}y zBT>0XNf5V_qd6bM4#D=vKrdBHp6i?D3{Uk`+Lob2LP5j*{G02u9fuM{k76abd^WMl z(X`G4eGA~A!VAt-pzuEWCUr5Tj*ehB+x!i{jZX%MPJK9VDFe=2y07P7wk|Xj^M*rW zHbfvl_+o^G6rH-Xj8YddN~W?zaIA|QAPS1#0%Yp1ZJ@4)?e-Mw<$7EPLI9Dx$JZ{8 zUFN8DA`bB}n1)Lh;_1KSCgsI`PV?yEIK2Gu+G^S{E^xGyH`Qzbgsb>QN=Cw>6RyZ4 zNM(F#qTaDKQsl6wQI+@W!9%yq9KYhU5L~!gKtAIz$0{LA5To`&8pASuIo(wjdHxF~ z>;3mU`VD&F*qo@&`4>h8@G%ps=s=>^to@RcYb$B{6`|D^Uvx z4Hlr|8{tf{@m(~gXLdv{%JAp59oYm4zm6Iow(b7`B!KaZ-W#iM7$Hm3hpVK`T z4aKvRb~Go9nOu6@GFTHZQzn$rlO+iDP=);X2mz-u5nKt#)u$yd?=lAwerZArK-#ku zuAup-%ri`FD5f)wS)?53-;H|DdVmVNp>d1^Q>07yNjur}H#dPGgO*#x{oqj9@fn?l$e1WUS=D1sGz`fh0_%=#kF0sN{h_ePUzq56!nx|o z6x^oot|!kR!tWTx`I8Dop!wpw1@+sKO_&%CIBBmXjJ+vZk)S(Cr@=4)#c&~$Vy1|5 zI#5y?z+&@Kmy_^gkvfa3QCvBJyuEzfYokY;DjLs8&e;V$o?g82Bp$q5FIx&!CMLHg zKidhnRiDcq__vL_x5Qy(0X+S)&jwKeMh>)s`4J5?Za-jZirP52UyIfcr;sop2w~1X z++?!m`0P7#~Ai1GAXKM~b`1>t{MHcX_`$S=T_9}KX^{n%AbN6Wd9@l%;#IGwFQ>~D6IU#z-9u6z*<${PXW8CJ0&!I>u3(+qM0YG<>C&t)0T_=E!!@;`yoh{n#7^CC&iB3U z%s&@NcQwgcgaa%57q@hpt(acOV%v1Evf<>7BC&eHsN^OZ378!0r!80X%y%vAL@c!1 z4juDac_(H6?~rvGOvE*_CT3<(I(R=kr;SN1y!8w0R*6h=*QT6}+{$0mN|w1|I1(5{ z6=9fVI+L^;Pt0||5ZO;yrIYpnyx{9K>nhGl>#dbKj_YWS{w!)E_ANf2!vwqt^SI2u zgq5}8(T*}ART~Ki(3!`8a9lk4S7GMn?G@B`&R<=41ehnwFMr`zHj%O(s$lsWuDw*- zcx=gCf2t7p_-->=Pu-?|W?v*G4nyF86^pux%OM~hk8YM%GFX(J#^muoh<^8`1a049 zN@XL7^30bIr}~6(qi3kf#!T081lw`qHU8wFLouD^D0G`vzF7G2R0y0WOsMBLsApVW zu0Ss1uBi17nKY!)8?m=Go^D!hdO5^R_==57PBh+-|MO%PiR>lZmX=SA?{=d(*ximM z)YziZhTq2XAp(TaM{Dp5SBGbC`J6luLF3gubWo|E#bsnNOK}_bs3o1XsNN-5uxm(# zZEjcDC*0!NovVa}J~dAL1fz_eAEG&K!tw;xm(D7~2=PV@1a~YNae^6v;t4w}`Nonj zAkZ zu^{`&*LYHluTa;zjGW!e(_F)wtySFYHUf1sja7=gt~ohzn!XeKNH zs_(aZ{dqHhSbIyhuAEU=X`)XggQY{dpzOc^{I42$m2%*#@%jmsqjN5m0(>+o>)DL- z#h*gM8W9yJ8BGxrT#Br|neQNXK$UkMi%(kN0BvMA zctxclsf2}}1aul~H1#yU4n(Q)B5%kixvPF-WCYf(jr-f#t|hS2=uQ}C_KIbIvbh=- z)J!Wkb*o8zj72=%D`mGG zS0E(0@~FeqS~6Q=c}D6xK-5`cK&AgzfSCu8V7yc+E%*LGb*SiRkf@N6sS04Xv>Mgo$mWuVV2A9>XNWn0Sch|ut#1V=+%REKA-u>objw)%T6Ja@SIpm?` zZ=JZ^-Ac=El5^54SVb)Kt!9(|4d}tthvthHpdc;lmz|U(QuX?44=?B0&Uo~NAxEM0 z1+?N4K5#I-orRTb-=gggpWD4h-g0Hp=Mdk67;ar#1T&D3N?E-}Wo?1uzOnx^i6!8x z;_1J>V77d=Um|~`WOEX^KjA@06*`%@yMRe3s-@(hC6ppZ`@P1`4O2OPaUFXnIs*NS zB4Y7%r)%yMrlZw-o{rt|W3s+h+dh34 zL)v=u{z9dH8_V7?eb;>k!g~aKJ};6)+J{8hY5c-OF@TRt#2NGj5ME+V;VqpZS`=xQ zsUA!u{$N4aEl;q;Q1+E#a&ujF)|AubC!vTNocLsn>(G==ZzGsuJ2-C*R!NOHeNf38 zS01=SU`{tOs7;e3oiToYl{dThN6=uMU)S zkhTM92-u9nuwy6}Je5?Mc2iCYUg>$nAZI-kqhmW56q-3|xG#;*liR5z;`OzYYcYP6 z?~>IcDa(-JBb|Ha=8Po2rk<3z5%8>6J%=|14>Ody1*73o-oLI2isBZ8Cp zBe;K@yxT8-@$A1SUcbt3KeT|E!`WKY~gd~TUrB0T=vAksa!Nx znwz8Ae*&JqJhI0yoD|-NrESEYk%PU#_}J(k01+sf55cL@P@WNrvo7`$ps_5oK&d$t z!wISLAawy5D!+v*2Zu=>*Dh5I_~t4Nz9OhQk^Y+$tHi$!D8mV+bDWxT=JPs2L3(tK z^f}IE+=w?XtmY3-o{VY1fckz_^B#R*@tn!1C~iPqdN7BLzATj;!?5ru`Y(jbGJpK} z`?OofCUdFe!&jCW=(UY{d*PI2AR&J&X!hmBXHS-iwSr=+hWf{A`Nq-#6n@0L!&{BA} zeG$(cvgEjYe~`ytOHQZ}mz zlrm{)JSKTkDOZsR==}MyEF{2$@%#wz;s2asTL71>=g%jwE$2ss zgegH)909=m6K*B0fHmL5ZxyRj*@#aW08Co$FupJ5zVE9wl@9Z6#?0i<)9z)vf^5(4 znL}?qWmgSN>p1R*#=8%_C32kFMK+j7AxxqHNm9yU_6OSNHUcYd7Fm{AN15E)dEjX)Bqw3Fa> zGU*D!MuKVGSKJz^4AoDmB$`Yp0lRwiHR?-5o`*QnL!)Myn-mJW7{`cn-E z=u~TefklDbAo$$P2RUygbGJvu|4r-qL(P;zddWc^q6=VwnY%aN0Jih;7_8Koc`a&N zUd3|fqW;&bEEQx|d(B)PFeO`g!bXbn##e;Kpz|;bh1!uj-3EZ+6t#-I>kk+0Y^m%| z+Fbe0kQf$>I==qwM0##p>n+sQqial~PjdR!k?!X+-~qGXRV<4*bacGRoY|7*;akx` z5WV7g6A^{Qm1_nr0yZ+c6asuO zL}>cXyoHe0ZlcF$0?{lSw6&`Y6@^lB#Yk$32tu(@#04Xifn~aB)Yya=Ix6s@ytnk-vK0`Dpy|Eioyg!#&T-%;c2tMz`CpOzl`b zcNx%DsB0}gI3`Me>8$3wlxw=znCXDO5pPjD{MgaGaj4C@)%fJ1;?xb#7KPzXl25Sk zmWaA_%-D1#l0|d+?N{G;vC@bEmMsu0hrR?on&|qd%`2MA0ogE7rfmOjAjPX&a$GLa z+o=vKCE_Mmec`C$i0A$xiEZdo+gcYW=85!eyNui#Z*bFyOWWpYB!F(=;jS?Ee=_-x zV9)zX|5{%SI-gSC?xNMS_6^+h@WU){ao_Ly+)7

k~#d_X#Y(Ej<6*JrCgM5ULj= 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�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

yL_#S@auZd* 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±$$ECwTUw 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
    kO~h78 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 ^OE{VOzLn>+Q(K6V=^$^ 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

    coe5jtnyAD}= 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%0DjroaS-h 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

    d2%1*XWk- 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 z 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 L{an^LB{Ts5piFpH literal 0 HcmV?d00001 diff --git a/protocol-designer/src/assets/localization/en/modal.json b/protocol-designer/src/assets/localization/en/modal.json index 8530f61a28a..62d34d00a9d 100644 --- a/protocol-designer/src/assets/localization/en/modal.json +++ b/protocol-designer/src/assets/localization/en/modal.json @@ -57,6 +57,16 @@ "body3": "Add multiple Heater-Shaker Modules and Magnetic Blocks to the deck (Flex only).", "body4": "All protocols now require Opentrons App version 8.2.0+ to run.", "body5": "For more information, see the Protocol Designer Instruction Manual." + }, + "absorbancePlateReaderSupport": { + "heading": "{{version}} Release Notes", + "body1": "Welcome to Protocol Designer {{version}}!", + "body2": "This release includes the following improvements:", + "body3": "Protocol Designer now supports the Absorbance Plate Reader Module", + "body4": "Bug fix for mismatched x- and y-offset values for aspirate and dispense during Mix steps", + "body5": "Bug fix for Move steps not using the gripper by default", + "body6": "All protocols now require Opentrons App version 8.2.0+ to run.", + "body7": "For more information, see the Protocol Designer Instruction Manual." } }, "labware_selection": { diff --git a/protocol-designer/src/organisms/AnnouncementModal/announcements.tsx b/protocol-designer/src/organisms/AnnouncementModal/announcements.tsx index e84930a26c0..2a745cd7d9a 100644 --- a/protocol-designer/src/organisms/AnnouncementModal/announcements.tsx +++ b/protocol-designer/src/organisms/AnnouncementModal/announcements.tsx @@ -9,6 +9,7 @@ import { Link as LinkComponent, SPACING, StyledText, + TEXT_DECORATION_UNDERLINE, } from '@opentrons/components' import magTempCombined from '../../assets/images/modules/magdeck_tempdeck_combined.png' @@ -19,7 +20,8 @@ import heaterShaker from '../../assets/images/modules/heatershaker.png' import thermocyclerGen2 from '../../assets/images/modules/thermocycler_gen2.png' import liquidEnhancements from '../../assets/images/announcements/liquid-enhancements.gif' import opentronsFlex from '../../assets/images/OpentronsFlex.png' -import deckConfigutation from '../../assets/images/deck_configuration.png' +import deckConfiguration from '../../assets/images/deck_configuration.png' +import absorbancePlateReaderImage from '../../assets/images/opentrons_absorbance_plate_reader.png' import { DOC_URL } from '../KnowledgeLink' import type { ReactNode } from 'react' @@ -53,6 +55,8 @@ const batchEditStyles = css` const PD = 'Protocol Designer' const APP = 'Opentrons App' const OPENTRONS_PD = 'Opentrons Protocol Designer' +const OPENTRONS_ABSORBANCE_READER_URL = + 'https://opentrons.com/products/opentrons-flex-absorbance-plate-reader-module-gen1' export const useAnnouncements = (): Announcement[] => { const { t } = useTranslation('modal') @@ -277,7 +281,7 @@ export const useAnnouncements = (): Announcement[] => { announcementKey: 'deckConfigAnd96Channel8.0', image: ( - + ), heading: t('announcements.header', { pd: PD }), @@ -372,5 +376,85 @@ export const useAnnouncements = (): Announcement[] => { ), }, + { + announcementKey: 'absorbancePlateReader', + image: ( + + + + ), + heading: t('announcements.absorbancePlateReaderSupport.heading', { + version: pdVersion, + }), + message: ( + + + {t('announcements.absorbancePlateReaderSupport.body1', { + version: pdVersion, + })} + + + + {t('announcements.absorbancePlateReaderSupport.body2')} + + +
      +
    • + + + ), + }} + i18nKey="announcements.absorbancePlateReaderSupport.body3" + /> + +
    • +
    • + + {t('announcements.absorbancePlateReaderSupport.body4')} + +
    • +
    • + + {t('announcements.absorbancePlateReaderSupport.body5')} + +
    • +
    +
    +
    + + {t('announcements.absorbancePlateReaderSupport.body6')} + + + + ), + }} + i18nKey="announcements.absorbancePlateReaderSupport.body7" + /> + +
    + ), + }, ] } From bb5b5cd64e576c60179279a49523fe4b6ff37580 Mon Sep 17 00:00:00 2001 From: Jeremy Leon Date: Tue, 28 Jan 2025 14:00:39 -0500 Subject: [PATCH 05/22] feat(api): add new InstrumentContext.consolidate_liquid() method (#17359) Adds consolidate_liquid method to instrument context --- .../protocol_api/core/engine/instrument.py | 12 + .../opentrons/protocol_api/core/instrument.py | 17 ++ .../core/legacy/legacy_instrument_core.py | 13 + .../legacy_instrument_core.py | 13 + .../protocol_api/instrument_context.py | 88 ++++++ .../protocol_api/test_instrument_context.py | 262 ++++++++++++++++++ 6 files changed, 405 insertions(+) diff --git a/api/src/opentrons/protocol_api/core/engine/instrument.py b/api/src/opentrons/protocol_api/core/engine/instrument.py index 9ae9b349789..2453436c0f6 100644 --- a/api/src/opentrons/protocol_api/core/engine/instrument.py +++ b/api/src/opentrons/protocol_api/core/engine/instrument.py @@ -1110,6 +1110,18 @@ def distribute_liquid( ) -> None: pass + def consolidate_liquid( + self, + liquid_class: LiquidClass, + volume: float, + source: List[Tuple[Location, WellCore]], + dest: Tuple[Location, WellCore], + new_tip: TransferTipPolicyV2, + tip_racks: List[Tuple[Location, LabwareCore]], + trash_location: Union[Location, TrashBin, WasteChute], + ) -> None: + pass + def _get_location_and_well_core_from_next_tip_info( self, tip_info: NextTipInfo, diff --git a/api/src/opentrons/protocol_api/core/instrument.py b/api/src/opentrons/protocol_api/core/instrument.py index aa653dccaea..18742262fa8 100644 --- a/api/src/opentrons/protocol_api/core/instrument.py +++ b/api/src/opentrons/protocol_api/core/instrument.py @@ -343,6 +343,23 @@ def distribute_liquid( """ ... + @abstractmethod + def consolidate_liquid( + self, + liquid_class: LiquidClass, + volume: float, + source: List[Tuple[types.Location, WellCoreType]], + dest: Tuple[types.Location, WellCoreType], + new_tip: TransferTipPolicyV2, + tip_racks: List[Tuple[types.Location, LabwareCoreType]], + trash_location: Union[types.Location, TrashBin, WasteChute], + ) -> None: + """ + Consolidate liquid from multiple sources to a single destination + using the specified liquid class properties. + """ + ... + @abstractmethod def is_tip_tracking_available(self) -> bool: """Return whether auto tip tracking is available for the pipette's current nozzle configuration.""" diff --git a/api/src/opentrons/protocol_api/core/legacy/legacy_instrument_core.py b/api/src/opentrons/protocol_api/core/legacy/legacy_instrument_core.py index 46cf36de2e9..81846122715 100644 --- a/api/src/opentrons/protocol_api/core/legacy/legacy_instrument_core.py +++ b/api/src/opentrons/protocol_api/core/legacy/legacy_instrument_core.py @@ -586,6 +586,19 @@ def distribute_liquid( """This will never be called because it was added in API 2.23""" assert False, "distribute_liquid is not supported in legacy context" + def consolidate_liquid( + self, + liquid_class: LiquidClass, + volume: float, + source: List[Tuple[types.Location, LegacyWellCore]], + dest: Tuple[types.Location, LegacyWellCore], + new_tip: TransferTipPolicyV2, + tip_racks: List[Tuple[types.Location, LegacyLabwareCore]], + trash_location: Union[types.Location, TrashBin, WasteChute], + ) -> None: + """This will never be called because it was added in API 2.23.""" + assert False, "consolidate_liquid is not supported in legacy context" + def get_active_channels(self) -> int: """This will never be called because it was added in API 2.16.""" assert False, "get_active_channels only supported in API 2.16 & later" diff --git a/api/src/opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py b/api/src/opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py index 93445f94f05..3b8792117d9 100644 --- a/api/src/opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +++ b/api/src/opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py @@ -506,6 +506,19 @@ def distribute_liquid( """This will never be called because it was added in API 2.23.""" assert False, "distribute_liquid is not supported in legacy context" + def consolidate_liquid( + self, + liquid_class: LiquidClass, + volume: float, + source: List[Tuple[types.Location, LegacyWellCore]], + dest: Tuple[types.Location, LegacyWellCore], + new_tip: TransferTipPolicyV2, + tip_racks: List[Tuple[types.Location, LegacyLabwareCore]], + trash_location: Union[types.Location, TrashBin, WasteChute], + ) -> None: + """This will never be called because it was added in API 2.23.""" + assert False, "consolidate_liquid is not supported in legacy context" + def get_active_channels(self) -> int: """This will never be called because it was added in API 2.16.""" assert False, "get_active_channels only supported in API 2.16 & later" diff --git a/api/src/opentrons/protocol_api/instrument_context.py b/api/src/opentrons/protocol_api/instrument_context.py index 11552ef9ec3..6192b35670a 100644 --- a/api/src/opentrons/protocol_api/instrument_context.py +++ b/api/src/opentrons/protocol_api/instrument_context.py @@ -1689,6 +1689,94 @@ def distribute_liquid( ) return self + def consolidate_liquid( + self, + liquid_class: LiquidClass, + volume: float, + source: Union[ + labware.Well, Sequence[labware.Well], Sequence[Sequence[labware.Well]] + ], + dest: labware.Well, + new_tip: TransferTipPolicyV2Type = "once", + trash_location: Optional[ + Union[types.Location, labware.Well, TrashBin, WasteChute] + ] = None, + ) -> InstrumentContext: + """ + Consolidate liquid from multiple sources to a single destination + using the specified liquid class properties. + + TODO: Add args description. + """ + if not feature_flags.allow_liquid_classes( + robot_type=RobotTypeEnum.robot_literal_to_enum( + self._protocol_core.robot_type + ) + ): + raise NotImplementedError("This method is not implemented.") + if not isinstance(dest, labware.Well): + raise ValueError( + f"Destination should be a single Well but received {dest}." + ) + flat_sources_list = validation.ensure_valid_flat_wells_list_for_transfer_v2( + source + ) + for well in flat_sources_list + [dest]: + instrument.validate_takes_liquid( + location=well.top(), + reject_module=True, + reject_adapter=True, + ) + + valid_new_tip = validation.ensure_new_tip_policy(new_tip) + if valid_new_tip == TransferTipPolicyV2.NEVER: + if self._last_tip_picked_up_from is None: + raise RuntimeError( + "Pipette has no tip attached to perform transfer." + " Either do a pick_up_tip beforehand or specify a new_tip parameter" + " of 'once' or 'always'." + ) + else: + tip_racks = [self._last_tip_picked_up_from.parent] + else: + tip_racks = self._tip_racks + if self.current_volume != 0: + raise RuntimeError( + "A transfer on a liquid class cannot start with liquid already in the tip." + " Ensure that all previously aspirated liquid is dispensed before starting" + " a new transfer." + ) + + _trash_location: Union[types.Location, labware.Well, TrashBin, WasteChute] + if trash_location is None: + saved_trash = self.trash_container + if isinstance(saved_trash, labware.Labware): + _trash_location = saved_trash.wells()[0] + else: + _trash_location = saved_trash + else: + _trash_location = trash_location + + checked_trash_location = validation.ensure_valid_trash_location_for_transfer_v2( + trash_location=_trash_location + ) + self._core.consolidate_liquid( + liquid_class=liquid_class, + volume=volume, + source=[ + (types.Location(types.Point(), labware=well), well._core) + for well in flat_sources_list + ], + dest=(types.Location(types.Point(), labware=dest), dest._core), + new_tip=valid_new_tip, + tip_racks=[ + (types.Location(types.Point(), labware=rack), rack._core) + for rack in tip_racks + ], + trash_location=checked_trash_location, + ) + return self + @requires_version(2, 0) def delay(self, *args: Any, **kwargs: Any) -> None: """ diff --git a/api/tests/opentrons/protocol_api/test_instrument_context.py b/api/tests/opentrons/protocol_api/test_instrument_context.py index 2a279ca1ad7..7fad487086a 100644 --- a/api/tests/opentrons/protocol_api/test_instrument_context.py +++ b/api/tests/opentrons/protocol_api/test_instrument_context.py @@ -2247,3 +2247,265 @@ def test_distribute_liquid_delegates_to_engine_core( trash_location=trash_location.move(Point(1, 2, 3)), ) ) + + +@pytest.mark.parametrize("robot_type", ["OT-2 Standard", "OT-3 Standard"]) +def test_consolidate_liquid_raises_for_invalid_locations( + decoy: Decoy, + mock_protocol_core: ProtocolCore, + subject: InstrumentContext, + mock_feature_flags: None, + robot_type: RobotType, + minimal_liquid_class_def2: LiquidClassSchemaV1, +) -> None: + """It should raise errors if source or destination is invalid.""" + test_liq_class = LiquidClass.create(minimal_liquid_class_def2) + mock_well = decoy.mock(cls=Well) + decoy.when(mock_protocol_core.robot_type).then_return(robot_type) + decoy.when( + ff.allow_liquid_classes(RobotTypeEnum.robot_literal_to_enum(robot_type)) + ).then_return(True) + decoy.when( + mock_validation.ensure_valid_flat_wells_list_for_transfer_v2([[mock_well]]) + ).then_raise(ValueError("Oh no")) + with pytest.raises(ValueError): + subject.consolidate_liquid( + liquid_class=test_liq_class, + volume=10, + source=[[mock_well]], + dest=mock_well, + ) + with pytest.raises(ValueError, match="Destination should be a single Well"): + subject.consolidate_liquid( + liquid_class=test_liq_class, + volume=10, + source=[mock_well], + dest="abc", # type: ignore + ) + + +@pytest.mark.parametrize("robot_type", ["OT-2 Standard", "OT-3 Standard"]) +def test_consolidate_liquid_raises_if_more_than_one_destination( + decoy: Decoy, + mock_protocol_core: ProtocolCore, + subject: InstrumentContext, + mock_feature_flags: None, + robot_type: RobotType, + minimal_liquid_class_def2: LiquidClassSchemaV1, +) -> None: + """It should raise error if destination is more than one well.""" + test_liq_class = LiquidClass.create(minimal_liquid_class_def2) + mock_well = decoy.mock(cls=Well) + decoy.when(mock_protocol_core.robot_type).then_return(robot_type) + decoy.when( + ff.allow_liquid_classes(RobotTypeEnum.robot_literal_to_enum(robot_type)) + ).then_return(True) + with pytest.raises(ValueError, match="Destination should be a single Well"): + subject.consolidate_liquid( + liquid_class=test_liq_class, + volume=10, + source=[mock_well, mock_well], + dest=[mock_well, mock_well], # type: ignore + ) + + +@pytest.mark.parametrize("robot_type", ["OT-2 Standard", "OT-3 Standard"]) +def test_consolidate_liquid_raises_for_non_liquid_handling_locations( + decoy: Decoy, + mock_protocol_core: ProtocolCore, + subject: InstrumentContext, + mock_feature_flags: None, + robot_type: RobotType, + minimal_liquid_class_def2: LiquidClassSchemaV1, +) -> None: + """It should raise errors if sources or destination are not a valid liquid handling target.""" + test_liq_class = LiquidClass.create(minimal_liquid_class_def2) + mock_well = decoy.mock(cls=Well) + decoy.when(mock_protocol_core.robot_type).then_return(robot_type) + decoy.when( + ff.allow_liquid_classes(RobotTypeEnum.robot_literal_to_enum(robot_type)) + ).then_return(True) + decoy.when( + mock_validation.ensure_valid_flat_wells_list_for_transfer_v2([mock_well]) + ).then_return([mock_well]) + decoy.when( + mock_instrument_support.validate_takes_liquid( + mock_well.top(), reject_module=True, reject_adapter=True + ) + ).then_raise(ValueError("Uh oh")) + with pytest.raises(ValueError, match="Uh oh"): + subject.consolidate_liquid( + liquid_class=test_liq_class, volume=10, source=[mock_well], dest=mock_well + ) + + +@pytest.mark.parametrize("robot_type", ["OT-2 Standard", "OT-3 Standard"]) +def test_consolidate_liquid_raises_for_bad_tip_policy( + decoy: Decoy, + mock_protocol_core: ProtocolCore, + subject: InstrumentContext, + mock_feature_flags: None, + robot_type: RobotType, + minimal_liquid_class_def2: LiquidClassSchemaV1, +) -> None: + """It should raise errors if new_tip is invalid.""" + test_liq_class = LiquidClass.create(minimal_liquid_class_def2) + mock_well = decoy.mock(cls=Well) + decoy.when(mock_protocol_core.robot_type).then_return(robot_type) + decoy.when( + ff.allow_liquid_classes(RobotTypeEnum.robot_literal_to_enum(robot_type)) + ).then_return(True) + decoy.when( + mock_validation.ensure_valid_flat_wells_list_for_transfer_v2([mock_well]) + ).then_return([mock_well]) + decoy.when(mock_validation.ensure_new_tip_policy("once")).then_raise( + ValueError("Uh oh") + ) + with pytest.raises(ValueError, match="Uh oh"): + subject.consolidate_liquid( + liquid_class=test_liq_class, + volume=10, + source=[mock_well], + dest=mock_well, + new_tip="once", + ) + + +@pytest.mark.parametrize("robot_type", ["OT-2 Standard", "OT-3 Standard"]) +def test_consolidate_liquid_raises_for_no_tip( + decoy: Decoy, + mock_protocol_core: ProtocolCore, + subject: InstrumentContext, + mock_feature_flags: None, + robot_type: RobotType, + minimal_liquid_class_def2: LiquidClassSchemaV1, +) -> None: + """It should raise errors if there is no tip attached.""" + test_liq_class = LiquidClass.create(minimal_liquid_class_def2) + mock_well = decoy.mock(cls=Well) + decoy.when(mock_protocol_core.robot_type).then_return(robot_type) + decoy.when( + ff.allow_liquid_classes(RobotTypeEnum.robot_literal_to_enum(robot_type)) + ).then_return(True) + decoy.when( + mock_validation.ensure_valid_flat_wells_list_for_transfer_v2([mock_well]) + ).then_return([mock_well]) + decoy.when(mock_validation.ensure_new_tip_policy("never")).then_return( + TransferTipPolicyV2.NEVER + ) + with pytest.raises(RuntimeError, match="Pipette has no tip"): + subject.consolidate_liquid( + liquid_class=test_liq_class, + volume=10, + source=[mock_well], + dest=mock_well, + new_tip="never", + ) + + +@pytest.mark.parametrize("robot_type", ["OT-2 Standard", "OT-3 Standard"]) +def test_consolidate_liquid_raises_if_tip_has_liquid( + decoy: Decoy, + mock_protocol_core: ProtocolCore, + mock_instrument_core: InstrumentCore, + subject: InstrumentContext, + mock_feature_flags: None, + robot_type: RobotType, + minimal_liquid_class_def2: LiquidClassSchemaV1, +) -> None: + """It should raise errors if there is liquid in the tip.""" + test_liq_class = LiquidClass.create(minimal_liquid_class_def2) + mock_well = decoy.mock(cls=Well) + tip_racks = [decoy.mock(cls=Labware)] + + subject.starting_tip = None + subject.tip_racks = tip_racks + + decoy.when(mock_protocol_core.robot_type).then_return(robot_type) + decoy.when( + ff.allow_liquid_classes(RobotTypeEnum.robot_literal_to_enum(robot_type)) + ).then_return(True) + decoy.when( + mock_validation.ensure_valid_flat_wells_list_for_transfer_v2([mock_well]) + ).then_return([mock_well]) + decoy.when(mock_validation.ensure_new_tip_policy("never")).then_return( + TransferTipPolicyV2.ONCE + ) + decoy.when(mock_instrument_core.get_nozzle_map()).then_return(MOCK_MAP) + decoy.when(mock_instrument_core.get_active_channels()).then_return(2) + decoy.when( + labware.next_available_tip( + starting_tip=None, + tip_racks=tip_racks, + channels=2, + nozzle_map=MOCK_MAP, + ) + ).then_return((decoy.mock(cls=Labware), decoy.mock(cls=Well))) + decoy.when(mock_instrument_core.get_current_volume()).then_return(1000) + with pytest.raises(RuntimeError, match="liquid already in the tip"): + subject.consolidate_liquid( + liquid_class=test_liq_class, + volume=10, + source=[mock_well], + dest=mock_well, + new_tip="never", + ) + + +@pytest.mark.parametrize("robot_type", ["OT-2 Standard", "OT-3 Standard"]) +def test_consolidate_liquid_delegates_to_engine_core( + decoy: Decoy, + mock_protocol_core: ProtocolCore, + mock_instrument_core: InstrumentCore, + subject: InstrumentContext, + mock_feature_flags: None, + robot_type: RobotType, + minimal_liquid_class_def2: LiquidClassSchemaV1, +) -> None: + """It should delegate the execution to core.""" + test_liq_class = LiquidClass.create(minimal_liquid_class_def2) + mock_well = decoy.mock(cls=Well) + tip_racks = [decoy.mock(cls=Labware)] + trash_location = Location(point=Point(1, 2, 3), labware=mock_well) + next_tiprack = decoy.mock(cls=Labware) + subject.starting_tip = None + subject._tip_racks = tip_racks + + decoy.when(mock_protocol_core.robot_type).then_return(robot_type) + decoy.when( + ff.allow_liquid_classes(RobotTypeEnum.robot_literal_to_enum(robot_type)) + ).then_return(True) + decoy.when( + mock_validation.ensure_valid_flat_wells_list_for_transfer_v2([mock_well]) + ).then_return([mock_well]) + decoy.when(mock_validation.ensure_new_tip_policy("never")).then_return( + TransferTipPolicyV2.ONCE + ) + decoy.when(mock_instrument_core.get_nozzle_map()).then_return(MOCK_MAP) + decoy.when(mock_instrument_core.get_active_channels()).then_return(2) + decoy.when(mock_instrument_core.get_current_volume()).then_return(0) + decoy.when( + mock_validation.ensure_valid_trash_location_for_transfer_v2(trash_location) + ).then_return(trash_location.move(Point(1, 2, 3))) + decoy.when(next_tiprack.uri).then_return("tiprack-uri") + decoy.when(mock_instrument_core.get_pipette_name()).then_return("pipette-name") + + subject.consolidate_liquid( + liquid_class=test_liq_class, + volume=10, + source=[mock_well], + dest=mock_well, + new_tip="never", + trash_location=trash_location, + ) + decoy.verify( + mock_instrument_core.consolidate_liquid( + liquid_class=test_liq_class, + volume=10, + source=[(Location(Point(), labware=mock_well), mock_well._core)], + dest=(Location(Point(), labware=mock_well), mock_well._core), + new_tip=TransferTipPolicyV2.ONCE, + tip_racks=[(Location(Point(), labware=tip_racks[0]), tip_racks[0]._core)], + trash_location=trash_location.move(Point(1, 2, 3)), + ) + ) From 410bfa9c68f3891863b4846ac14037f0a32b4d95 Mon Sep 17 00:00:00 2001 From: Sanniti Pimpley Date: Tue, 28 Jan 2025 14:12:24 -0500 Subject: [PATCH 06/22] feat(api): introduce correction volume into the liquid classes based transfer flow (#17322) Closes AUTH-964 # Overview Adds `correctionVolume` to protocol engine's aspirate and dispense commands and also adds it as argument to rest of the steps in the pipeline to get the correction volume value from the transfer flow to hardware controller. The hardware controller then wires it up to move the plunger in proportion to the correction volume. ## Risk assessment Low --------- Co-authored-by: Andy Sigler --- api/src/opentrons/hardware_control/api.py | 2 + .../instruments/ot3/pipette_handler.py | 27 +- api/src/opentrons/hardware_control/ot3api.py | 13 +- .../protocols/liquid_handler.py | 4 + .../protocol_api/core/engine/instrument.py | 19 +- .../engine/transfer_components_executor.py | 17 +- .../opentrons/protocol_api/core/instrument.py | 9 +- .../core/legacy/legacy_instrument_core.py | 8 +- .../legacy_instrument_core.py | 6 +- .../commands/air_gap_in_place.py | 2 + .../protocol_engine/commands/aspirate.py | 2 + .../commands/aspirate_in_place.py | 2 + .../protocol_engine/commands/dispense.py | 2 + .../commands/dispense_in_place.py | 2 + .../commands/pipetting_common.py | 24 +- .../protocol_engine/execution/pipetting.py | 15 +- .../core/engine/test_instrument_core.py | 26 +- .../test_transfer_components_executor.py | 99 +- .../core/simulator/test_instrument_context.py | 10 + .../commands/test_air_gap_in_place.py | 4 + .../protocol_engine/commands/test_aspirate.py | 5 + .../commands/test_aspirate_in_place.py | 3 + .../protocol_engine/commands/test_dispense.py | 12 +- .../commands/test_dispense_in_place.py | 7 +- .../execution/test_pipetting_handler.py | 8 +- shared-data/command/schemas/12.json | 6468 +++++++++++++++++ 26 files changed, 6759 insertions(+), 37 deletions(-) create mode 100644 shared-data/command/schemas/12.json diff --git a/api/src/opentrons/hardware_control/api.py b/api/src/opentrons/hardware_control/api.py index c52fae64131..a5dbae274fb 100644 --- a/api/src/opentrons/hardware_control/api.py +++ b/api/src/opentrons/hardware_control/api.py @@ -1039,6 +1039,7 @@ async def aspirate( mount: top_types.Mount, volume: Optional[float] = None, rate: float = 1.0, + correction_volume: float = 0.0, ) -> None: """ Aspirate a volume of liquid (in microliters/uL) using this pipette. @@ -1073,6 +1074,7 @@ async def dispense( volume: Optional[float] = None, rate: float = 1.0, push_out: Optional[float] = None, + correction_volume: float = 0.0, ) -> None: """ Dispense a volume of liquid in microliters(uL) using this pipette. diff --git a/api/src/opentrons/hardware_control/instruments/ot3/pipette_handler.py b/api/src/opentrons/hardware_control/instruments/ot3/pipette_handler.py index ef081b95a62..7c553584500 100644 --- a/api/src/opentrons/hardware_control/instruments/ot3/pipette_handler.py +++ b/api/src/opentrons/hardware_control/instruments/ot3/pipette_handler.py @@ -502,10 +502,19 @@ def ready_for_tip_action( self._ihp_log.debug(f"{action} on {target.name}") def plunger_position( - self, instr: Pipette, ul: float, action: "UlPerMmAction" + self, + instr: Pipette, + ul: float, + action: "UlPerMmAction", + correction_volume: float = 0.0, ) -> float: - mm = ul / instr.ul_per_mm(ul, action) - position = instr.plunger_positions.bottom - mm + if ul == 0: + position = instr.plunger_positions.bottom + else: + multiplier = 1.0 + (correction_volume / ul) + mm_dist_from_bottom = ul / instr.ul_per_mm(ul, action) + mm_dist_from_bottom_corrected = mm_dist_from_bottom * multiplier + position = instr.plunger_positions.bottom - mm_dist_from_bottom_corrected return round(position, 6) def plunger_speed( @@ -531,6 +540,7 @@ def plan_check_aspirate( mount: OT3Mount, volume: Optional[float], rate: float, + correction_volume: float = 0.0, ) -> Optional[LiquidActionSpec]: """Check preconditions for aspirate, parse args, and calculate positions. @@ -566,7 +576,10 @@ def plan_check_aspirate( ), "Cannot aspirate more than pipette max volume" dist = self.plunger_position( - instrument, instrument.current_volume + asp_vol, "aspirate" + instr=instrument, + ul=instrument.current_volume + asp_vol, + action="aspirate", + correction_volume=correction_volume, ) speed = self.plunger_speed( instrument, instrument.aspirate_flow_rate * rate, "aspirate" @@ -591,6 +604,7 @@ def plan_check_dispense( volume: Optional[float], rate: float, push_out: Optional[float], + correction_volume: float = 0.0, ) -> Optional[LiquidActionSpec]: """Check preconditions for dispense, parse args, and calculate positions. @@ -659,7 +673,10 @@ def plan_check_dispense( ) dist = self.plunger_position( - instrument, instrument.current_volume - disp_vol, "dispense" + instr=instrument, + ul=instrument.current_volume - disp_vol, + action="dispense", + correction_volume=correction_volume, ) speed = self.plunger_speed( instrument, instrument.dispense_flow_rate * rate, "dispense" diff --git a/api/src/opentrons/hardware_control/ot3api.py b/api/src/opentrons/hardware_control/ot3api.py index 6295757e7ab..bf59793d9dc 100644 --- a/api/src/opentrons/hardware_control/ot3api.py +++ b/api/src/opentrons/hardware_control/ot3api.py @@ -2046,12 +2046,16 @@ async def aspirate( mount: Union[top_types.Mount, OT3Mount], volume: Optional[float] = None, rate: float = 1.0, + correction_volume: float = 0.0, ) -> None: """ Aspirate a volume of liquid (in microliters/uL) using this pipette.""" realmount = OT3Mount.from_mount(mount) aspirate_spec = self._pipette_handler.plan_check_aspirate( - realmount, volume, rate + mount=realmount, + volume=volume, + rate=rate, + correction_volume=correction_volume, ) if not aspirate_spec: return @@ -2088,12 +2092,17 @@ async def dispense( volume: Optional[float] = None, rate: float = 1.0, push_out: Optional[float] = None, + correction_volume: float = 0.0, ) -> None: """ Dispense a volume of liquid in microliters(uL) using this pipette.""" realmount = OT3Mount.from_mount(mount) dispense_spec = self._pipette_handler.plan_check_dispense( - realmount, volume, rate, push_out + mount=realmount, + volume=volume, + rate=rate, + push_out=push_out, + correction_volume=correction_volume, ) if not dispense_spec: return diff --git a/api/src/opentrons/hardware_control/protocols/liquid_handler.py b/api/src/opentrons/hardware_control/protocols/liquid_handler.py index 2aea15bd55b..045a21795ea 100644 --- a/api/src/opentrons/hardware_control/protocols/liquid_handler.py +++ b/api/src/opentrons/hardware_control/protocols/liquid_handler.py @@ -98,6 +98,7 @@ async def aspirate( mount: MountArgType, volume: Optional[float] = None, rate: float = 1.0, + correction_volume: float = 0.0, ) -> None: """ Aspirate a volume of liquid (in microliters/uL) using this pipette @@ -117,6 +118,7 @@ async def aspirate( volume : [float] The number of microliters to aspirate rate : [float] Set plunger speed for this aspirate, where speed = rate * aspirate_speed + correction_volume : Correction volume in uL for the specified aspirate volume """ ... @@ -126,6 +128,7 @@ async def dispense( volume: Optional[float] = None, rate: float = 1.0, push_out: Optional[float] = None, + correction_volume: float = 0.0, ) -> None: """ Dispense a volume of liquid in microliters(uL) using this pipette @@ -136,6 +139,7 @@ async def dispense( volume : [float] The number of microliters to dispense rate : [float] Set plunger speed for this dispense, where speed = rate * dispense_speed + correction_volume : Correction volume in uL for the specified dispense volume """ ... diff --git a/api/src/opentrons/protocol_api/core/engine/instrument.py b/api/src/opentrons/protocol_api/core/engine/instrument.py index 2453436c0f6..30ace69e63b 100644 --- a/api/src/opentrons/protocol_api/core/engine/instrument.py +++ b/api/src/opentrons/protocol_api/core/engine/instrument.py @@ -126,7 +126,9 @@ def set_default_speed(self, speed: float) -> None: pipette_id=self._pipette_id, speed=speed ) - def air_gap_in_place(self, volume: float, flow_rate: float) -> None: + def air_gap_in_place( + self, volume: float, flow_rate: float, correction_volume: Optional[float] = None + ) -> None: """Aspirate a given volume of air from the current location of the pipette. Args: @@ -135,7 +137,10 @@ def air_gap_in_place(self, volume: float, flow_rate: float) -> None: """ self._engine_client.execute_command( cmd.AirGapInPlaceParams( - pipetteId=self._pipette_id, volume=volume, flowRate=flow_rate + pipetteId=self._pipette_id, + volume=volume, + flowRate=flow_rate, + correctionVolume=correction_volume, ) ) @@ -148,6 +153,7 @@ def aspirate( flow_rate: float, in_place: bool, is_meniscus: Optional[bool] = None, + correction_volume: Optional[float] = None, ) -> None: """Aspirate a given volume of liquid from the specified location. Args: @@ -174,7 +180,10 @@ def aspirate( self._engine_client.execute_command( cmd.AspirateInPlaceParams( - pipetteId=self._pipette_id, volume=volume, flowRate=flow_rate + pipetteId=self._pipette_id, + volume=volume, + flowRate=flow_rate, + correctionVolume=correction_volume, ) ) @@ -205,6 +214,7 @@ def aspirate( wellLocation=well_location, volume=volume, flowRate=flow_rate, + correctionVolume=correction_volume, ) ) @@ -220,6 +230,7 @@ def dispense( in_place: bool, push_out: Optional[float], is_meniscus: Optional[bool] = None, + correction_volume: Optional[float] = None, ) -> None: """Dispense a given volume of liquid into the specified location. Args: @@ -267,6 +278,7 @@ def dispense( volume=volume, flowRate=flow_rate, pushOut=push_out, + correctionVolume=correction_volume, ) ) else: @@ -297,6 +309,7 @@ def dispense( volume=volume, flowRate=flow_rate, pushOut=push_out, + correctionVolume=correction_volume, ) ) diff --git a/api/src/opentrons/protocol_api/core/engine/transfer_components_executor.py b/api/src/opentrons/protocol_api/core/engine/transfer_components_executor.py index 7dc332e6a37..cf61e41909c 100644 --- a/api/src/opentrons/protocol_api/core/engine/transfer_components_executor.py +++ b/api/src/opentrons/protocol_api/core/engine/transfer_components_executor.py @@ -161,6 +161,7 @@ def aspirate_and_wait(self, volume: float) -> None: """Aspirate according to aspirate properties and wait if enabled.""" # TODO: handle volume correction aspirate_props = self._transfer_properties.aspirate + correction_volume = aspirate_props.correction_by_volume.get_for_volume(volume) self._instrument.aspirate( location=self._target_location, well_core=None, @@ -169,6 +170,7 @@ def aspirate_and_wait(self, volume: float) -> None: flow_rate=aspirate_props.flow_rate_by_volume.get_for_volume(volume), in_place=True, is_meniscus=None, # TODO: update this once meniscus is implemented + correction_volume=correction_volume, ) self._tip_state.append_liquid(volume) delay_props = aspirate_props.delay @@ -183,6 +185,7 @@ def dispense_and_wait( """Dispense according to dispense properties and wait if enabled.""" # TODO: handle volume correction dispense_props = self._transfer_properties.dispense + correction_volume = dispense_props.correction_by_volume.get_for_volume(volume) self._instrument.dispense( location=self._target_location, well_core=None, @@ -192,6 +195,7 @@ def dispense_and_wait( in_place=True, push_out=push_out_override, is_meniscus=None, + correction_volume=correction_volume, ) if push_out_override: # If a push out was performed, we need to reset the plunger before we can aspirate again @@ -504,12 +508,19 @@ def _add_air_gap(self, air_gap_volume: float) -> None: if air_gap_volume == 0: return aspirate_props = self._transfer_properties.aspirate + correction_volume = aspirate_props.correction_by_volume.get_for_volume( + air_gap_volume + ) # The maximum flow rate should be air_gap_volume per second flow_rate = min( aspirate_props.flow_rate_by_volume.get_for_volume(air_gap_volume), air_gap_volume, ) - self._instrument.air_gap_in_place(volume=air_gap_volume, flow_rate=flow_rate) + self._instrument.air_gap_in_place( + volume=air_gap_volume, + flow_rate=flow_rate, + correction_volume=correction_volume, + ) delay_props = aspirate_props.delay if delay_props.enabled: # Assertion only for mypy purposes @@ -524,6 +535,9 @@ def _remove_air_gap(self, location: Location) -> None: return dispense_props = self._transfer_properties.dispense + correction_volume = dispense_props.correction_by_volume.get_for_volume( + last_air_gap + ) # The maximum flow rate should be air_gap_volume per second flow_rate = min( dispense_props.flow_rate_by_volume.get_for_volume(last_air_gap), @@ -538,6 +552,7 @@ def _remove_air_gap(self, location: Location) -> None: in_place=True, is_meniscus=None, push_out=0, + correction_volume=correction_volume, ) self._tip_state.delete_air_gap(last_air_gap) dispense_delay = dispense_props.delay diff --git a/api/src/opentrons/protocol_api/core/instrument.py b/api/src/opentrons/protocol_api/core/instrument.py index 18742262fa8..4a60cf8f19e 100644 --- a/api/src/opentrons/protocol_api/core/instrument.py +++ b/api/src/opentrons/protocol_api/core/instrument.py @@ -26,11 +26,14 @@ def set_default_speed(self, speed: float) -> None: ... @abstractmethod - def air_gap_in_place(self, volume: float, flow_rate: float) -> None: + def air_gap_in_place( + self, volume: float, flow_rate: float, correction_volume: Optional[float] = None + ) -> None: """Aspirate a given volume of air from the current location of the pipette. Args: volume: The volume of air to aspirate, in microliters. flow_rate: The flow rate of air into the pipette, in microliters. + correction_volume: The correction volume in uL. """ @abstractmethod @@ -43,6 +46,7 @@ def aspirate( flow_rate: float, in_place: bool, is_meniscus: Optional[bool] = None, + correction_volume: Optional[float] = None, ) -> None: """Aspirate a given volume of liquid from the specified location. Args: @@ -52,6 +56,7 @@ def aspirate( rate: The rate for how quickly to aspirate. flow_rate: The flow rate in µL/s to aspirate at. in_place: Whether this is in-place. + correction_volume: The correction volume in uL """ ... @@ -66,6 +71,7 @@ def dispense( in_place: bool, push_out: Optional[float], is_meniscus: Optional[bool] = None, + correction_volume: Optional[float] = None, ) -> None: """Dispense a given volume of liquid into the specified location. Args: @@ -76,6 +82,7 @@ def dispense( flow_rate: The flow rate in µL/s to dispense at. in_place: Whether this is in-place. push_out: The amount to push the plunger below bottom position. + correction_volume: The correction volume in uL """ ... diff --git a/api/src/opentrons/protocol_api/core/legacy/legacy_instrument_core.py b/api/src/opentrons/protocol_api/core/legacy/legacy_instrument_core.py index 81846122715..5572ef440d9 100644 --- a/api/src/opentrons/protocol_api/core/legacy/legacy_instrument_core.py +++ b/api/src/opentrons/protocol_api/core/legacy/legacy_instrument_core.py @@ -74,7 +74,9 @@ def set_default_speed(self, speed: float) -> None: """Sets the speed at which the robot's gantry moves.""" self._default_speed = speed - def air_gap_in_place(self, volume: float, flow_rate: float) -> None: + def air_gap_in_place( + self, volume: float, flow_rate: float, correction_volume: Optional[float] = None + ) -> None: assert False, "Air gap tracking only available in API version 2.22 and later" def aspirate( @@ -86,6 +88,7 @@ def aspirate( flow_rate: float, in_place: bool, is_meniscus: Optional[bool] = None, + correction_volume: Optional[float] = None, ) -> None: """Aspirate a given volume of liquid from the specified location. Args: @@ -95,6 +98,7 @@ def aspirate( rate: The rate in µL/s to aspirate at. flow_rate: Not used in this core. in_place: Whether we should move_to location. + correction_volume: Not used in this core """ if self.get_current_volume() == 0: # Make sure we're at the top of the labware and clear of any @@ -129,6 +133,7 @@ def dispense( in_place: bool, push_out: Optional[float], is_meniscus: Optional[bool] = None, + correction_volume: Optional[float] = None, ) -> None: """Dispense a given volume of liquid into the specified location. Args: @@ -138,6 +143,7 @@ def dispense( rate: The rate in µL/s to dispense at. flow_rate: Not used in this core. in_place: Whether we should move_to location. + correction_volume: Not used in this core. push_out: The amount to push the plunger below bottom position. """ if isinstance(location, (TrashBin, WasteChute)): diff --git a/api/src/opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py b/api/src/opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py index 3b8792117d9..8c2c570ad1c 100644 --- a/api/src/opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +++ b/api/src/opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py @@ -87,7 +87,9 @@ def get_default_speed(self) -> float: def set_default_speed(self, speed: float) -> None: self._default_speed = speed - def air_gap_in_place(self, volume: float, flow_rate: float) -> None: + def air_gap_in_place( + self, volume: float, flow_rate: float, correction_volume: Optional[float] = None + ) -> None: assert False, "Air gap tracking only available in API version 2.22 and later" def aspirate( @@ -99,6 +101,7 @@ def aspirate( flow_rate: float, in_place: bool, is_meniscus: Optional[bool] = None, + correction_volume: Optional[float] = None, ) -> None: if self.get_current_volume() == 0: # Make sure we're at the top of the labware and clear of any @@ -141,6 +144,7 @@ def dispense( in_place: bool, push_out: Optional[float], is_meniscus: Optional[bool] = None, + correction_volume: Optional[float] = None, ) -> None: if isinstance(location, (TrashBin, WasteChute)): raise APIVersionError( diff --git a/api/src/opentrons/protocol_engine/commands/air_gap_in_place.py b/api/src/opentrons/protocol_engine/commands/air_gap_in_place.py index 461a446f3e4..bf6bbafc3d5 100644 --- a/api/src/opentrons/protocol_engine/commands/air_gap_in_place.py +++ b/api/src/opentrons/protocol_engine/commands/air_gap_in_place.py @@ -14,6 +14,7 @@ FlowRateMixin, BaseLiquidHandlingResult, OverpressureError, + DEFAULT_CORRECTION_VOLUME, ) from .command import ( AbstractCommandImpl, @@ -103,6 +104,7 @@ async def execute(self, params: AirGapInPlaceParams) -> _ExecuteReturn: volume=params.volume, flow_rate=params.flowRate, command_note_adder=self._command_note_adder, + correction_volume=params.correctionVolume or DEFAULT_CORRECTION_VOLUME, ) except PipetteOverpressureError as e: return DefinedErrorData( diff --git a/api/src/opentrons/protocol_engine/commands/aspirate.py b/api/src/opentrons/protocol_engine/commands/aspirate.py index b07cd522f93..708ee3ecbdb 100644 --- a/api/src/opentrons/protocol_engine/commands/aspirate.py +++ b/api/src/opentrons/protocol_engine/commands/aspirate.py @@ -12,6 +12,7 @@ BaseLiquidHandlingResult, aspirate_in_place, prepare_for_aspirate, + DEFAULT_CORRECTION_VOLUME, ) from .movement_common import ( LiquidHandlingWellLocationMixin, @@ -182,6 +183,7 @@ async def execute(self, params: AspirateParams) -> _ExecuteReturn: command_note_adder=self._command_note_adder, pipetting=self._pipetting, model_utils=self._model_utils, + correction_volume=params.correctionVolume or DEFAULT_CORRECTION_VOLUME, ) state_update.append(aspirate_result.state_update) if isinstance(aspirate_result, DefinedErrorData): diff --git a/api/src/opentrons/protocol_engine/commands/aspirate_in_place.py b/api/src/opentrons/protocol_engine/commands/aspirate_in_place.py index 434924928d7..a5e68d7c1f0 100644 --- a/api/src/opentrons/protocol_engine/commands/aspirate_in_place.py +++ b/api/src/opentrons/protocol_engine/commands/aspirate_in_place.py @@ -13,6 +13,7 @@ BaseLiquidHandlingResult, OverpressureError, aspirate_in_place, + DEFAULT_CORRECTION_VOLUME, ) from .command import ( AbstractCommandImpl, @@ -108,6 +109,7 @@ async def execute(self, params: AspirateInPlaceParams) -> _ExecuteReturn: command_note_adder=self._command_note_adder, pipetting=self._pipetting, model_utils=self._model_utils, + correction_volume=params.correctionVolume or DEFAULT_CORRECTION_VOLUME, ) if isinstance(result, DefinedErrorData): if ( diff --git a/api/src/opentrons/protocol_engine/commands/dispense.py b/api/src/opentrons/protocol_engine/commands/dispense.py index 8ad2365ccb5..d1290190c64 100644 --- a/api/src/opentrons/protocol_engine/commands/dispense.py +++ b/api/src/opentrons/protocol_engine/commands/dispense.py @@ -16,6 +16,7 @@ BaseLiquidHandlingResult, OverpressureError, dispense_in_place, + DEFAULT_CORRECTION_VOLUME, ) from .movement_common import ( LiquidHandlingWellLocationMixin, @@ -117,6 +118,7 @@ async def execute(self, params: DispenseParams) -> _ExecuteReturn: }, pipetting=self._pipetting, model_utils=self._model_utils, + correction_volume=params.correctionVolume or DEFAULT_CORRECTION_VOLUME, ) if isinstance(dispense_result, DefinedErrorData): diff --git a/api/src/opentrons/protocol_engine/commands/dispense_in_place.py b/api/src/opentrons/protocol_engine/commands/dispense_in_place.py index 117aa011a84..ff09f5444ee 100644 --- a/api/src/opentrons/protocol_engine/commands/dispense_in_place.py +++ b/api/src/opentrons/protocol_engine/commands/dispense_in_place.py @@ -13,6 +13,7 @@ BaseLiquidHandlingResult, OverpressureError, dispense_in_place, + DEFAULT_CORRECTION_VOLUME, ) from .command import ( AbstractCommandImpl, @@ -95,6 +96,7 @@ async def execute(self, params: DispenseInPlaceParams) -> _ExecuteReturn: }, pipetting=self._pipetting, model_utils=self._model_utils, + correction_volume=params.correctionVolume or DEFAULT_CORRECTION_VOLUME, ) if isinstance(result, DefinedErrorData): if ( diff --git a/api/src/opentrons/protocol_engine/commands/pipetting_common.py b/api/src/opentrons/protocol_engine/commands/pipetting_common.py index 6740a4babb3..c0bca3c428a 100644 --- a/api/src/opentrons/protocol_engine/commands/pipetting_common.py +++ b/api/src/opentrons/protocol_engine/commands/pipetting_common.py @@ -1,7 +1,7 @@ """Common pipetting command base models.""" from __future__ import annotations -from typing import Literal, Tuple, TYPE_CHECKING +from typing import Literal, Tuple, TYPE_CHECKING, Optional from typing_extensions import TypedDict from pydantic import BaseModel, Field @@ -20,6 +20,10 @@ from ..notes import CommandNoteAdder +DEFAULT_CORRECTION_VOLUME = 0.0 +"""Default correction volume (uL) for any aspirate/ dispense volume.""" + + class PipetteIdMixin(BaseModel): """Mixin for command requests that take a pipette ID.""" @@ -41,6 +45,11 @@ class AspirateVolumeMixin(BaseModel): " There is some tolerance for floating point rounding errors.", ge=0, ) + correctionVolume: Optional[float] = Field( + None, + description="The correction volume in uL.", + ge=0, + ) class DispenseVolumeMixin(BaseModel): @@ -53,6 +62,11 @@ class DispenseVolumeMixin(BaseModel): " There is some tolerance for floating point rounding errors.", ge=0, ) + correctionVolume: Optional[float] = Field( + None, + description="The correction volume in uL.", + ge=0, + ) class FlowRateMixin(BaseModel): @@ -176,18 +190,20 @@ async def aspirate_in_place( pipette_id: str, volume: float, flow_rate: float, + correction_volume: float, location_if_error: ErrorLocationInfo, command_note_adder: CommandNoteAdder, pipetting: PipettingHandler, model_utils: ModelUtils, ) -> SuccessData[BaseLiquidHandlingResult] | DefinedErrorData[OverpressureError]: - """Execute an aspirate in place microoperation.""" + """Execute an aspirate in place micro-operation.""" try: volume_aspirated = await pipetting.aspirate_in_place( pipette_id=pipette_id, volume=volume, flow_rate=flow_rate, command_note_adder=command_note_adder, + correction_volume=correction_volume, ) except PipetteOverpressureError as e: return DefinedErrorData( @@ -320,17 +336,19 @@ async def dispense_in_place( volume: float, flow_rate: float, push_out: float | None, + correction_volume: float, location_if_error: ErrorLocationInfo, pipetting: PipettingHandler, model_utils: ModelUtils, ) -> SuccessData[BaseLiquidHandlingResult] | DefinedErrorData[OverpressureError]: - """Dispense-in-place as a microoperation.""" + """Dispense-in-place as a micro-operation.""" try: volume = await pipetting.dispense_in_place( pipette_id=pipette_id, volume=volume, flow_rate=flow_rate, push_out=push_out, + correction_volume=correction_volume, ) except PipetteOverpressureError as e: return DefinedErrorData( diff --git a/api/src/opentrons/protocol_engine/execution/pipetting.py b/api/src/opentrons/protocol_engine/execution/pipetting.py index 0cbca0f9079..7c45479387d 100644 --- a/api/src/opentrons/protocol_engine/execution/pipetting.py +++ b/api/src/opentrons/protocol_engine/execution/pipetting.py @@ -42,6 +42,7 @@ async def aspirate_in_place( volume: float, flow_rate: float, command_note_adder: CommandNoteAdder, + correction_volume: float = 0.0, ) -> float: """Set flow-rate and aspirate.""" @@ -73,6 +74,7 @@ async def dispense_in_place( volume: float, flow_rate: float, push_out: Optional[float], + correction_volume: float = 0.0, ) -> float: """Set flow-rate and dispense.""" @@ -195,6 +197,7 @@ async def aspirate_in_place( volume: float, flow_rate: float, command_note_adder: CommandNoteAdder, + correction_volume: float = 0.0, ) -> float: """Set flow-rate and aspirate. @@ -207,7 +210,9 @@ async def aspirate_in_place( ) with self._set_flow_rate(pipette=hw_pipette, aspirate_flow_rate=flow_rate): await self._hardware_api.aspirate( - mount=hw_pipette.mount, volume=adjusted_volume + mount=hw_pipette.mount, + volume=adjusted_volume, + correction_volume=correction_volume, ) return adjusted_volume @@ -218,6 +223,7 @@ async def dispense_in_place( volume: float, flow_rate: float, push_out: Optional[float], + correction_volume: float = 0.0, ) -> float: """Dispense liquid without moving the pipette.""" hw_pipette, adjusted_volume = self.get_hw_dispense_params(pipette_id, volume) @@ -228,7 +234,10 @@ async def dispense_in_place( ) with self._set_flow_rate(pipette=hw_pipette, dispense_flow_rate=flow_rate): await self._hardware_api.dispense( - mount=hw_pipette.mount, volume=adjusted_volume, push_out=push_out + mount=hw_pipette.mount, + volume=adjusted_volume, + push_out=push_out, + correction_volume=correction_volume, ) return adjusted_volume @@ -326,6 +335,7 @@ async def aspirate_in_place( volume: float, flow_rate: float, command_note_adder: CommandNoteAdder, + correction_volume: float = 0.0, ) -> float: """Virtually aspirate (no-op).""" self._validate_tip_attached(pipette_id=pipette_id, command_name="aspirate") @@ -342,6 +352,7 @@ async def dispense_in_place( volume: float, flow_rate: float, push_out: Optional[float], + correction_volume: float = 0.0, ) -> float: """Virtually dispense (no-op).""" # TODO (tz, 8-23-23): add a check for push_out not larger that the max volume allowed when working on this https://opentrons.atlassian.net/browse/RSS-329 diff --git a/api/tests/opentrons/protocol_api/core/engine/test_instrument_core.py b/api/tests/opentrons/protocol_api/core/engine/test_instrument_core.py index 9a3ecaad69b..8ac1ffc1dc8 100644 --- a/api/tests/opentrons/protocol_api/core/engine/test_instrument_core.py +++ b/api/tests/opentrons/protocol_api/core/engine/test_instrument_core.py @@ -599,6 +599,7 @@ def test_aspirate_from_well( rate=5.6, flow_rate=7.8, in_place=False, + correction_volume=123, ) decoy.verify( @@ -621,6 +622,7 @@ def test_aspirate_from_well( ), volume=12.34, flowRate=7.8, + correctionVolume=123, ) ), mock_protocol_core.set_last_location(location=location, mount=Mount.LEFT), @@ -659,6 +661,7 @@ def test_aspirate_from_coordinates( pipetteId="abc123", volume=12.34, flowRate=7.8, + correctionVolume=None, ) ), mock_protocol_core.set_last_location(location=location, mount=Mount.LEFT), @@ -725,6 +728,7 @@ def test_aspirate_from_meniscus( ), volume=12.34, flowRate=7.8, + correctionVolume=None, ) ), mock_protocol_core.set_last_location(location=location, mount=Mount.LEFT), @@ -754,6 +758,7 @@ def test_aspirate_in_place( pipetteId="abc123", volume=12.34, flowRate=7.8, + correctionVolume=None, ) ), mock_protocol_core.set_last_location(location=location, mount=Mount.LEFT), @@ -896,6 +901,7 @@ def test_dispense_to_well( rate=5.6, flow_rate=6.0, in_place=False, + correction_volume=321, push_out=7, ) @@ -919,6 +925,7 @@ def test_dispense_to_well( ), volume=12.34, flowRate=6.0, + correctionVolume=321, pushOut=7, ) ), @@ -948,7 +955,11 @@ def test_dispense_in_place( decoy.verify( mock_engine_client.execute_command( cmd.DispenseInPlaceParams( - pipetteId="abc123", volume=12.34, flowRate=7.8, pushOut=None + pipetteId="abc123", + volume=12.34, + correctionVolume=None, + flowRate=7.8, + pushOut=None, ) ), ) @@ -985,7 +996,11 @@ def test_dispense_to_coordinates( ), mock_engine_client.execute_command( cmd.DispenseInPlaceParams( - pipetteId="abc123", volume=12.34, flowRate=7.8, pushOut=None + pipetteId="abc123", + volume=12.34, + correctionVolume=None, + flowRate=7.8, + pushOut=None, ) ), ) @@ -1023,7 +1038,11 @@ def test_dispense_conditionally_clamps_volume( decoy.verify( mock_engine_client.execute_command( cmd.DispenseInPlaceParams( - pipetteId="abc123", volume=111.111, flowRate=7.8, pushOut=None + pipetteId="abc123", + volume=111.111, + correctionVolume=None, + flowRate=7.8, + pushOut=None, ) ), ) @@ -1034,6 +1053,7 @@ def test_dispense_conditionally_clamps_volume( pipetteId="abc123", volume=99999999.99999999, flowRate=7.8, + correctionVolume=None, pushOut=None, ) ), diff --git a/api/tests/opentrons/protocol_api/core/engine/test_transfer_components_executor.py b/api/tests/opentrons/protocol_api/core/engine/test_transfer_components_executor.py index 87870468590..4dadf5b503b 100644 --- a/api/tests/opentrons/protocol_api/core/engine/test_transfer_components_executor.py +++ b/api/tests/opentrons/protocol_api/core/engine/test_transfer_components_executor.py @@ -75,6 +75,9 @@ def test_submerge( air_gap_removal_flow_rate = ( sample_transfer_props.dispense.flow_rate_by_volume.get_for_volume(123) ) + air_gap_correction_vol = ( + sample_transfer_props.dispense.correction_by_volume.get_for_volume(123) + ) subject = TransferComponentsExecutor( instrument_core=mock_instrument_core, @@ -109,6 +112,7 @@ def test_submerge( in_place=True, is_meniscus=None, push_out=0, + correction_volume=air_gap_correction_vol, ), mock_instrument_core.delay(0.5), mock_instrument_core.move_to( @@ -132,7 +136,9 @@ def test_aspirate_and_wait( aspirate_flow_rate = ( sample_transfer_props.aspirate.flow_rate_by_volume.get_for_volume(10) ) - + correction_volume = ( + sample_transfer_props.aspirate.correction_by_volume.get_for_volume(10) + ) subject = TransferComponentsExecutor( instrument_core=mock_instrument_core, transfer_properties=sample_transfer_props, @@ -151,6 +157,7 @@ def test_aspirate_and_wait( flow_rate=aspirate_flow_rate, in_place=True, is_meniscus=None, + correction_volume=correction_volume, ), mock_instrument_core.delay(0.2), ) @@ -190,7 +197,9 @@ def test_dispense_and_wait( dispense_flow_rate = ( sample_transfer_props.dispense.flow_rate_by_volume.get_for_volume(10) ) - + correction_volume = ( + sample_transfer_props.dispense.correction_by_volume.get_for_volume(50) + ) subject = TransferComponentsExecutor( instrument_core=mock_instrument_core, transfer_properties=sample_transfer_props, @@ -210,6 +219,7 @@ def test_dispense_and_wait( in_place=True, push_out=123, is_meniscus=None, + correction_volume=correction_volume, ), mock_instrument_core.delay(0.5), ) @@ -252,6 +262,12 @@ def test_mix( dispense_flow_rate = ( sample_transfer_props.dispense.flow_rate_by_volume.get_for_volume(50) ) + aspirate_correction_volume = ( + sample_transfer_props.aspirate.correction_by_volume.get_for_volume(50) + ) + dispense_correction_volume = ( + sample_transfer_props.dispense.correction_by_volume.get_for_volume(50) + ) subject = TransferComponentsExecutor( instrument_core=mock_instrument_core, transfer_properties=sample_transfer_props, @@ -274,6 +290,7 @@ def test_mix( flow_rate=aspirate_flow_rate, in_place=True, is_meniscus=None, + correction_volume=aspirate_correction_volume, ), mock_instrument_core.delay(0.2), mock_instrument_core.dispense( @@ -285,6 +302,7 @@ def test_mix( in_place=True, push_out=2.0, is_meniscus=None, + correction_volume=dispense_correction_volume, ), mock_instrument_core.delay(0.5), ) @@ -301,6 +319,9 @@ def test_mix_disabled( aspirate_flow_rate = ( sample_transfer_props.aspirate.flow_rate_by_volume.get_for_volume(50) ) + correction_volume = ( + sample_transfer_props.aspirate.correction_by_volume.get_for_volume(50) + ) subject = TransferComponentsExecutor( instrument_core=mock_instrument_core, transfer_properties=sample_transfer_props, @@ -322,6 +343,7 @@ def test_mix_disabled( flow_rate=aspirate_flow_rate, in_place=True, is_meniscus=None, + correction_volume=correction_volume, ), times=0, ) @@ -340,6 +362,12 @@ def test_pre_wet( dispense_flow_rate = ( sample_transfer_props.dispense.flow_rate_by_volume.get_for_volume(40) ) + aspirate_correction_volume = ( + sample_transfer_props.aspirate.correction_by_volume.get_for_volume(50) + ) + dispense_correction_volume = ( + sample_transfer_props.dispense.correction_by_volume.get_for_volume(50) + ) subject = TransferComponentsExecutor( instrument_core=mock_instrument_core, transfer_properties=sample_transfer_props, @@ -359,6 +387,7 @@ def test_pre_wet( flow_rate=aspirate_flow_rate, in_place=True, is_meniscus=None, + correction_volume=aspirate_correction_volume, ), mock_instrument_core.delay(0.2), mock_instrument_core.dispense( @@ -370,6 +399,7 @@ def test_pre_wet( in_place=True, push_out=0, is_meniscus=None, + correction_volume=dispense_correction_volume, ), mock_instrument_core.delay(0.5), ) @@ -386,6 +416,9 @@ def test_pre_wet_disabled( aspirate_flow_rate = ( sample_transfer_props.aspirate.flow_rate_by_volume.get_for_volume(40) ) + aspirate_correction_volume = ( + sample_transfer_props.aspirate.correction_by_volume.get_for_volume(50) + ) subject = TransferComponentsExecutor( instrument_core=mock_instrument_core, transfer_properties=sample_transfer_props, @@ -405,6 +438,7 @@ def test_pre_wet_disabled( flow_rate=aspirate_flow_rate, in_place=True, is_meniscus=None, + correction_volume=aspirate_correction_volume, ), times=0, ) @@ -423,6 +457,11 @@ def test_retract_after_aspiration( air_gap_volume = ( sample_transfer_props.aspirate.retract.air_gap_by_volume.get_for_volume(40) ) + air_gap_correction_vol = ( + sample_transfer_props.aspirate.correction_by_volume.get_for_volume( + air_gap_volume + ) + ) subject = TransferComponentsExecutor( instrument_core=mock_instrument_core, @@ -464,6 +503,7 @@ def test_retract_after_aspiration( mock_instrument_core.air_gap_in_place( volume=air_gap_volume, flow_rate=air_gap_volume, + correction_volume=air_gap_correction_vol, ), mock_instrument_core.delay(0.2), ) @@ -485,7 +525,11 @@ def test_retract_after_aspiration_without_touch_tip_and_delay( air_gap_volume = ( sample_transfer_props.aspirate.retract.air_gap_by_volume.get_for_volume(40) ) - + air_gap_correction_vol = ( + sample_transfer_props.aspirate.correction_by_volume.get_for_volume( + air_gap_volume + ) + ) subject = TransferComponentsExecutor( instrument_core=mock_instrument_core, transfer_properties=sample_transfer_props, @@ -516,6 +560,7 @@ def test_retract_after_aspiration_without_touch_tip_and_delay( mock_instrument_core.air_gap_in_place( volume=air_gap_volume, flow_rate=air_gap_volume, + correction_volume=air_gap_correction_vol, ), mock_instrument_core.delay(0.2), ) @@ -570,6 +615,11 @@ def test_retract_after_dispense_with_blowout_in_source( air_gap_volume = ( sample_transfer_props.aspirate.retract.air_gap_by_volume.get_for_volume(0) ) + air_gap_correction_vol = ( + sample_transfer_props.aspirate.correction_by_volume.get_for_volume( + air_gap_volume + ) + ) subject = TransferComponentsExecutor( instrument_core=mock_instrument_core, transfer_properties=sample_transfer_props, @@ -612,7 +662,9 @@ def test_retract_after_dispense_with_blowout_in_source( speed=None, ), mock_instrument_core.air_gap_in_place( - volume=air_gap_volume, flow_rate=air_gap_volume + volume=air_gap_volume, + flow_rate=air_gap_volume, + correction_volume=air_gap_correction_vol, ), mock_instrument_core.delay(0.2), mock_instrument_core.set_flow_rate(blow_out=100), @@ -641,7 +693,9 @@ def test_retract_after_dispense_with_blowout_in_source( add_final_air_gap and [ mock_instrument_core.air_gap_in_place( # type: ignore[func-returns-value] - volume=air_gap_volume, flow_rate=air_gap_volume + volume=air_gap_volume, + flow_rate=air_gap_volume, + correction_volume=air_gap_correction_vol, ), mock_instrument_core.delay(0.2), # type: ignore[func-returns-value] ] @@ -668,6 +722,11 @@ def test_retract_after_dispense_with_blowout_in_destination( air_gap_volume = ( sample_transfer_props.aspirate.retract.air_gap_by_volume.get_for_volume(0) ) + air_gap_correction_vol = ( + sample_transfer_props.aspirate.correction_by_volume.get_for_volume( + air_gap_volume + ) + ) sample_transfer_props.dispense.retract.blowout.location = ( BlowoutLocation.DESTINATION ) @@ -729,7 +788,9 @@ def test_retract_after_dispense_with_blowout_in_destination( add_final_air_gap and [ mock_instrument_core.air_gap_in_place( # type: ignore[func-returns-value] - volume=air_gap_volume, flow_rate=air_gap_volume + volume=air_gap_volume, + flow_rate=air_gap_volume, + correction_volume=air_gap_correction_vol, ), mock_instrument_core.delay(0.2), # type: ignore[func-returns-value] ] @@ -760,6 +821,11 @@ def test_retract_after_dispense_with_blowout_in_trash_well( air_gap_volume = ( sample_transfer_props.aspirate.retract.air_gap_by_volume.get_for_volume(0) ) + air_gap_correction_vol = ( + sample_transfer_props.aspirate.correction_by_volume.get_for_volume( + air_gap_volume + ) + ) sample_transfer_props.dispense.retract.blowout.location = BlowoutLocation.TRASH subject = TransferComponentsExecutor( @@ -804,7 +870,9 @@ def test_retract_after_dispense_with_blowout_in_trash_well( speed=None, ), mock_instrument_core.air_gap_in_place( - volume=air_gap_volume, flow_rate=air_gap_volume + volume=air_gap_volume, + flow_rate=air_gap_volume, + correction_volume=air_gap_correction_vol, ), mock_instrument_core.delay(0.2), mock_instrument_core.set_flow_rate(blow_out=100), @@ -832,7 +900,9 @@ def test_retract_after_dispense_with_blowout_in_trash_well( add_final_air_gap and [ mock_instrument_core.air_gap_in_place( # type: ignore[func-returns-value] - volume=air_gap_volume, flow_rate=air_gap_volume + volume=air_gap_volume, + flow_rate=air_gap_volume, + correction_volume=air_gap_correction_vol, ), mock_instrument_core.delay(0.2), # type: ignore[func-returns-value] ] @@ -861,6 +931,11 @@ def test_retract_after_dispense_with_blowout_in_disposal_location( air_gap_volume = ( sample_transfer_props.aspirate.retract.air_gap_by_volume.get_for_volume(0) ) + air_gap_correction_vol = ( + sample_transfer_props.aspirate.correction_by_volume.get_for_volume( + air_gap_volume + ) + ) sample_transfer_props.dispense.retract.blowout.location = BlowoutLocation.TRASH subject = TransferComponentsExecutor( @@ -904,7 +979,9 @@ def test_retract_after_dispense_with_blowout_in_disposal_location( speed=None, ), mock_instrument_core.air_gap_in_place( - volume=air_gap_volume, flow_rate=air_gap_volume + volume=air_gap_volume, + flow_rate=air_gap_volume, + correction_volume=air_gap_correction_vol, ), mock_instrument_core.delay(0.2), mock_instrument_core.set_flow_rate(blow_out=100), @@ -917,7 +994,9 @@ def test_retract_after_dispense_with_blowout_in_disposal_location( add_final_air_gap and [ mock_instrument_core.air_gap_in_place( # type: ignore[func-returns-value] - volume=air_gap_volume, flow_rate=air_gap_volume + volume=air_gap_volume, + flow_rate=air_gap_volume, + correction_volume=air_gap_correction_vol, ), mock_instrument_core.delay(0.2), # type: ignore[func-returns-value] ] diff --git a/api/tests/opentrons/protocol_api_old/core/simulator/test_instrument_context.py b/api/tests/opentrons/protocol_api_old/core/simulator/test_instrument_context.py index c9bd57c0997..42e3f7aab67 100644 --- a/api/tests/opentrons/protocol_api_old/core/simulator/test_instrument_context.py +++ b/api/tests/opentrons/protocol_api_old/core/simulator/test_instrument_context.py @@ -59,6 +59,7 @@ def test_dispense_no_tip(subject: InstrumentCore) -> None: location=location, well_core=None, in_place=False, + correction_volume=0, push_out=None, ) @@ -106,6 +107,7 @@ def test_pick_up_tip_prep_after( rate=1, flow_rate=1, in_place=False, + correction_volume=0, ) subject.dispense( volume=1, @@ -114,6 +116,7 @@ def test_pick_up_tip_prep_after( location=Location(point=Point(2, 2, 3), labware=None), well_core=labware.get_well_core("A2"), in_place=False, + correction_volume=0, push_out=None, ) @@ -134,6 +137,7 @@ def test_pick_up_tip_prep_after( rate=1, flow_rate=1, in_place=False, + correction_volume=0, ) subject.dispense( volume=1, @@ -142,6 +146,7 @@ def test_pick_up_tip_prep_after( location=Location(point=Point(2, 2, 3), labware=None), well_core=labware.get_well_core("A2"), in_place=False, + correction_volume=0, push_out=None, ) @@ -173,6 +178,7 @@ def test_aspirate_too_much( rate=1, flow_rate=1, in_place=False, + correction_volume=0, ) @@ -224,6 +230,7 @@ def _aspirate(i: InstrumentCore, labware: LabwareCore) -> None: rate=10, flow_rate=10, in_place=False, + correction_volume=0, ) @@ -237,6 +244,7 @@ def _aspirate_dispense(i: InstrumentCore, labware: LabwareCore) -> None: rate=10, flow_rate=10, in_place=False, + correction_volume=0, ) i.dispense( volume=2, @@ -245,6 +253,7 @@ def _aspirate_dispense(i: InstrumentCore, labware: LabwareCore) -> None: location=Location(point=Point(2, 2, 3), labware=None), well_core=labware.get_well_core("A2"), in_place=False, + correction_volume=0, push_out=None, ) @@ -259,6 +268,7 @@ def _aspirate_blowout(i: InstrumentCore, labware: LabwareCore) -> None: rate=13, flow_rate=13, in_place=False, + correction_volume=0, ) i.blow_out( location=Location(point=Point(1, 2, 3), labware=None), diff --git a/api/tests/opentrons/protocol_engine/commands/test_air_gap_in_place.py b/api/tests/opentrons/protocol_engine/commands/test_air_gap_in_place.py index b9d110fd9c2..776912b4b18 100644 --- a/api/tests/opentrons/protocol_engine/commands/test_air_gap_in_place.py +++ b/api/tests/opentrons/protocol_engine/commands/test_air_gap_in_place.py @@ -101,6 +101,7 @@ async def test_air_gap_in_place_implementation( pipetteId="pipette-id-abc", volume=123, flowRate=1.234, + correctionVolume=321, ) decoy.when( @@ -115,6 +116,7 @@ async def test_air_gap_in_place_implementation( volume=123, flow_rate=1.234, command_note_adder=mock_command_note_adder, + correction_volume=321, ) ).then_return(123) @@ -194,6 +196,7 @@ async def test_aspirate_raises_volume_error( volume=50, flow_rate=1.23, command_note_adder=mock_command_note_adder, + correction_volume=0, ) ).then_raise(AssertionError("blah blah")) @@ -253,6 +256,7 @@ async def test_overpressure_error( volume=50, flow_rate=1.23, command_note_adder=mock_command_note_adder, + correction_volume=0, ), ).then_raise(PipetteOverpressureError()) diff --git a/api/tests/opentrons/protocol_engine/commands/test_aspirate.py b/api/tests/opentrons/protocol_engine/commands/test_aspirate.py index 4a8adbcdc76..ff09f9a966d 100644 --- a/api/tests/opentrons/protocol_engine/commands/test_aspirate.py +++ b/api/tests/opentrons/protocol_engine/commands/test_aspirate.py @@ -126,6 +126,7 @@ async def test_aspirate_implementation_no_prep( volume=50, flow_rate=1.23, command_note_adder=mock_command_note_adder, + correction_volume=0.0, ), ).then_return(50) @@ -236,6 +237,7 @@ async def test_aspirate_implementation_with_prep( volume=volume, flow_rate=flow_rate, command_note_adder=mock_command_note_adder, + correction_volume=0.0, ), ).then_return(volume) @@ -326,6 +328,7 @@ async def test_aspirate_raises_volume_error( volume=50, flow_rate=1.23, command_note_adder=mock_command_note_adder, + correction_volume=0.0, ) ).then_raise(AssertionError("blah blah")) @@ -402,6 +405,7 @@ async def test_overpressure_error( volume=50, flow_rate=1.23, command_note_adder=mock_command_note_adder, + correction_volume=0.0, ), ).then_raise(PipetteOverpressureError()) @@ -502,6 +506,7 @@ async def test_aspirate_implementation_meniscus( volume=50, flow_rate=1.23, command_note_adder=mock_command_note_adder, + correction_volume=0, ), ).then_return(50) diff --git a/api/tests/opentrons/protocol_engine/commands/test_aspirate_in_place.py b/api/tests/opentrons/protocol_engine/commands/test_aspirate_in_place.py index 5a7ca3ee940..464f8e04a82 100644 --- a/api/tests/opentrons/protocol_engine/commands/test_aspirate_in_place.py +++ b/api/tests/opentrons/protocol_engine/commands/test_aspirate_in_place.py @@ -129,6 +129,7 @@ async def test_aspirate_in_place_implementation( volume=123, flow_rate=1.234, command_note_adder=mock_command_note_adder, + correction_volume=0.0, ) ).then_return(123) @@ -221,6 +222,7 @@ async def test_aspirate_raises_volume_error( volume=50, flow_rate=1.23, command_note_adder=mock_command_note_adder, + correction_volume=0, ) ).then_raise(AssertionError("blah blah")) @@ -292,6 +294,7 @@ async def test_overpressure_error( volume=50, flow_rate=1.23, command_note_adder=mock_command_note_adder, + correction_volume=0, ), ).then_raise(PipetteOverpressureError()) diff --git a/api/tests/opentrons/protocol_engine/commands/test_dispense.py b/api/tests/opentrons/protocol_engine/commands/test_dispense.py index 5b60b61d4df..8fe72afe757 100644 --- a/api/tests/opentrons/protocol_engine/commands/test_dispense.py +++ b/api/tests/opentrons/protocol_engine/commands/test_dispense.py @@ -99,7 +99,11 @@ async def test_dispense_implementation( decoy.when( await pipetting.dispense_in_place( - pipette_id="pipette-id-abc123", volume=50, flow_rate=1.23, push_out=None + pipette_id="pipette-id-abc123", + volume=50, + flow_rate=1.23, + push_out=None, + correction_volume=0, ) ).then_return(42) decoy.when( @@ -193,7 +197,11 @@ async def test_overpressure_error( decoy.when( await pipetting.dispense_in_place( - pipette_id=pipette_id, volume=50, flow_rate=1.23, push_out=None + pipette_id=pipette_id, + volume=50, + flow_rate=1.23, + push_out=None, + correction_volume=0, ), ).then_raise(PipetteOverpressureError()) diff --git a/api/tests/opentrons/protocol_engine/commands/test_dispense_in_place.py b/api/tests/opentrons/protocol_engine/commands/test_dispense_in_place.py index e9c715223de..15b239e8d46 100644 --- a/api/tests/opentrons/protocol_engine/commands/test_dispense_in_place.py +++ b/api/tests/opentrons/protocol_engine/commands/test_dispense_in_place.py @@ -78,7 +78,11 @@ async def test_dispense_in_place_implementation( decoy.when( await pipetting.dispense_in_place( - pipette_id="pipette-id-abc", volume=123, flow_rate=456, push_out=None + pipette_id="pipette-id-abc", + volume=123, + flow_rate=456, + push_out=None, + correction_volume=0, ) ).then_return(42) @@ -195,6 +199,7 @@ async def test_overpressure_error( volume=50, flow_rate=1.23, push_out=10, + correction_volume=0, ), ).then_raise(PipetteOverpressureError()) diff --git a/api/tests/opentrons/protocol_engine/execution/test_pipetting_handler.py b/api/tests/opentrons/protocol_engine/execution/test_pipetting_handler.py index 84a425b88fc..f39853cb894 100644 --- a/api/tests/opentrons/protocol_engine/execution/test_pipetting_handler.py +++ b/api/tests/opentrons/protocol_engine/execution/test_pipetting_handler.py @@ -171,7 +171,9 @@ async def test_hw_dispense_in_place( mock_hardware_api.set_flow_rate( mount=Mount.RIGHT, aspirate=None, dispense=2.5, blow_out=None ), - await mock_hardware_api.dispense(mount=Mount.RIGHT, volume=25, push_out=None), + await mock_hardware_api.dispense( + mount=Mount.RIGHT, volume=25, push_out=None, correction_volume=0 + ), mock_hardware_api.set_flow_rate( mount=Mount.RIGHT, aspirate=1.23, dispense=4.56, blow_out=7.89 ), @@ -263,7 +265,9 @@ async def test_hw_aspirate_in_place( mock_hardware_api.set_flow_rate( mount=Mount.LEFT, aspirate=2.5, dispense=None, blow_out=None ), - await mock_hardware_api.aspirate(mount=Mount.LEFT, volume=25), + await mock_hardware_api.aspirate( + mount=Mount.LEFT, volume=25, correction_volume=0 + ), mock_hardware_api.set_flow_rate( mount=Mount.LEFT, aspirate=1.23, dispense=4.56, blow_out=7.89 ), diff --git a/shared-data/command/schemas/12.json b/shared-data/command/schemas/12.json new file mode 100644 index 00000000000..914e32a117b --- /dev/null +++ b/shared-data/command/schemas/12.json @@ -0,0 +1,6468 @@ +{ + "$defs": { + "AddressableAreaLocation": { + "description": "The location of something place in an addressable area. This is a superset of deck slots.", + "properties": { + "addressableAreaName": { + "description": "The name of the addressable area that you want to use. Valid values are the `id`s of `addressableArea`s in the [deck definition](https://github.com/Opentrons/opentrons/tree/edge/shared-data/deck).", + "title": "Addressableareaname", + "type": "string" + } + }, + "required": ["addressableAreaName"], + "title": "AddressableAreaLocation", + "type": "object" + }, + "AddressableOffsetVector": { + "description": "Offset, in deck coordinates, from nominal to actual position of an addressable area.", + "properties": { + "x": { + "title": "X", + "type": "number" + }, + "y": { + "title": "Y", + "type": "number" + }, + "z": { + "title": "Z", + "type": "number" + } + }, + "required": ["x", "y", "z"], + "title": "AddressableOffsetVector", + "type": "object" + }, + "AirGapInPlaceCreate": { + "description": "AirGapInPlace command request model.", + "properties": { + "commandType": { + "const": "airGapInPlace", + "default": "airGapInPlace", + "enum": ["airGapInPlace"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/AirGapInPlaceParams" + } + }, + "required": ["params"], + "title": "AirGapInPlaceCreate", + "type": "object" + }, + "AirGapInPlaceParams": { + "description": "Payload required to air gap in place.", + "properties": { + "correctionVolume": { + "anyOf": [ + { + "minimum": 0.0, + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The correction volume in uL.", + "title": "Correctionvolume" + }, + "flowRate": { + "description": "Speed in \u00b5L/s configured for the pipette", + "exclusiveMinimum": 0.0, + "title": "Flowrate", + "type": "number" + }, + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + }, + "volume": { + "description": "The amount of liquid to aspirate, in \u00b5L. Must not be greater than the remaining available amount, which depends on the pipette (see `loadPipette`), its configuration (see `configureForVolume`), the tip (see `pickUpTip`), and the amount you've aspirated so far. There is some tolerance for floating point rounding errors.", + "minimum": 0.0, + "title": "Volume", + "type": "number" + } + }, + "required": ["flowRate", "volume", "pipetteId"], + "title": "AirGapInPlaceParams", + "type": "object" + }, + "AllNozzleLayoutConfiguration": { + "description": "All basemodel to represent a reset to the nozzle configuration. Sending no parameters resets to default.", + "properties": { + "style": { + "const": "ALL", + "default": "ALL", + "enum": ["ALL"], + "title": "Style", + "type": "string" + } + }, + "title": "AllNozzleLayoutConfiguration", + "type": "object" + }, + "AspirateCreate": { + "description": "Create aspirate command request model.", + "properties": { + "commandType": { + "const": "aspirate", + "default": "aspirate", + "enum": ["aspirate"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/AspirateParams" + } + }, + "required": ["params"], + "title": "AspirateCreate", + "type": "object" + }, + "AspirateInPlaceCreate": { + "description": "AspirateInPlace command request model.", + "properties": { + "commandType": { + "const": "aspirateInPlace", + "default": "aspirateInPlace", + "enum": ["aspirateInPlace"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/AspirateInPlaceParams" + } + }, + "required": ["params"], + "title": "AspirateInPlaceCreate", + "type": "object" + }, + "AspirateInPlaceParams": { + "description": "Payload required to aspirate in place.", + "properties": { + "correctionVolume": { + "anyOf": [ + { + "minimum": 0.0, + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The correction volume in uL.", + "title": "Correctionvolume" + }, + "flowRate": { + "description": "Speed in \u00b5L/s configured for the pipette", + "exclusiveMinimum": 0.0, + "title": "Flowrate", + "type": "number" + }, + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + }, + "volume": { + "description": "The amount of liquid to aspirate, in \u00b5L. Must not be greater than the remaining available amount, which depends on the pipette (see `loadPipette`), its configuration (see `configureForVolume`), the tip (see `pickUpTip`), and the amount you've aspirated so far. There is some tolerance for floating point rounding errors.", + "minimum": 0.0, + "title": "Volume", + "type": "number" + } + }, + "required": ["flowRate", "volume", "pipetteId"], + "title": "AspirateInPlaceParams", + "type": "object" + }, + "AspirateParams": { + "description": "Parameters required to aspirate from a specific well.", + "properties": { + "correctionVolume": { + "anyOf": [ + { + "minimum": 0.0, + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The correction volume in uL.", + "title": "Correctionvolume" + }, + "flowRate": { + "description": "Speed in \u00b5L/s configured for the pipette", + "exclusiveMinimum": 0.0, + "title": "Flowrate", + "type": "number" + }, + "labwareId": { + "description": "Identifier of labware to use.", + "title": "Labwareid", + "type": "string" + }, + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + }, + "volume": { + "description": "The amount of liquid to aspirate, in \u00b5L. Must not be greater than the remaining available amount, which depends on the pipette (see `loadPipette`), its configuration (see `configureForVolume`), the tip (see `pickUpTip`), and the amount you've aspirated so far. There is some tolerance for floating point rounding errors.", + "minimum": 0.0, + "title": "Volume", + "type": "number" + }, + "wellLocation": { + "$ref": "#/$defs/LiquidHandlingWellLocation", + "description": "Relative well location at which to perform the operation" + }, + "wellName": { + "description": "Name of well to use in labware.", + "title": "Wellname", + "type": "string" + } + }, + "required": ["labwareId", "wellName", "flowRate", "volume", "pipetteId"], + "title": "AspirateParams", + "type": "object" + }, + "AspirateProperties": { + "description": "Properties specific to the aspirate function.", + "properties": { + "correctionByVolume": { + "description": "Settings for volume correction keyed by by target aspiration volume, representing additional volume the plunger should move to accurately hit target volume.", + "items": { + "maxItems": 2, + "minItems": 2, + "prefixItems": [ + { + "anyOf": [ + { + "minimum": 0, + "type": "integer" + }, + { + "minimum": 0.0, + "type": "number" + } + ] + }, + { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "number" + } + ] + } + ], + "type": "array" + }, + "title": "Correctionbyvolume", + "type": "array" + }, + "delay": { + "$ref": "#/$defs/DelayProperties", + "description": "Delay settings after an aspirate" + }, + "flowRateByVolume": { + "description": "Settings for flow rate keyed by target aspiration volume.", + "items": { + "maxItems": 2, + "minItems": 2, + "prefixItems": [ + { + "anyOf": [ + { + "minimum": 0, + "type": "integer" + }, + { + "minimum": 0.0, + "type": "number" + } + ] + }, + { + "anyOf": [ + { + "minimum": 0, + "type": "integer" + }, + { + "minimum": 0.0, + "type": "number" + } + ] + } + ], + "type": "array" + }, + "title": "Flowratebyvolume", + "type": "array" + }, + "mix": { + "$ref": "#/$defs/MixProperties", + "description": "Mixing settings for before an aspirate" + }, + "offset": { + "$ref": "#/$defs/Coordinate", + "description": "Relative offset for aspiration." + }, + "positionReference": { + "$ref": "#/$defs/PositionReference", + "description": "Position reference for aspiration." + }, + "preWet": { + "description": "Whether to perform a pre-wet action.", + "title": "Prewet", + "type": "boolean" + }, + "retract": { + "$ref": "#/$defs/RetractAspirate", + "description": "Pipette retract settings after an aspirate." + }, + "submerge": { + "$ref": "#/$defs/Submerge", + "description": "Submerge settings for aspirate." + } + }, + "required": [ + "submerge", + "retract", + "positionReference", + "offset", + "flowRateByVolume", + "correctionByVolume", + "preWet", + "mix", + "delay" + ], + "title": "AspirateProperties", + "type": "object" + }, + "AspirateWhileTrackingCreate": { + "description": "Create aspirateWhileTracking command request model.", + "properties": { + "commandType": { + "const": "aspirateWhileTracking", + "default": "aspirateWhileTracking", + "enum": ["aspirateWhileTracking"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/AspirateWhileTrackingParams" + } + }, + "required": ["params"], + "title": "AspirateWhileTrackingCreate", + "type": "object" + }, + "AspirateWhileTrackingParams": { + "description": "Parameters required to aspirate from a specific well.", + "properties": { + "correctionVolume": { + "anyOf": [ + { + "minimum": 0.0, + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The correction volume in uL.", + "title": "Correctionvolume" + }, + "flowRate": { + "description": "Speed in \u00b5L/s configured for the pipette", + "exclusiveMinimum": 0.0, + "title": "Flowrate", + "type": "number" + }, + "labwareId": { + "description": "Identifier of labware to use.", + "title": "Labwareid", + "type": "string" + }, + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + }, + "volume": { + "description": "The amount of liquid to aspirate, in \u00b5L. Must not be greater than the remaining available amount, which depends on the pipette (see `loadPipette`), its configuration (see `configureForVolume`), the tip (see `pickUpTip`), and the amount you've aspirated so far. There is some tolerance for floating point rounding errors.", + "minimum": 0.0, + "title": "Volume", + "type": "number" + }, + "wellLocation": { + "$ref": "#/$defs/LiquidHandlingWellLocation", + "description": "Relative well location at which to perform the operation" + }, + "wellName": { + "description": "Name of well to use in labware.", + "title": "Wellname", + "type": "string" + } + }, + "required": ["labwareId", "wellName", "flowRate", "volume", "pipetteId"], + "title": "AspirateWhileTrackingParams", + "type": "object" + }, + "BlowOutCreate": { + "description": "Create blow-out command request model.", + "properties": { + "commandType": { + "const": "blowout", + "default": "blowout", + "enum": ["blowout"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/BlowOutParams" + } + }, + "required": ["params"], + "title": "BlowOutCreate", + "type": "object" + }, + "BlowOutInPlaceCreate": { + "description": "BlowOutInPlace command request model.", + "properties": { + "commandType": { + "const": "blowOutInPlace", + "default": "blowOutInPlace", + "enum": ["blowOutInPlace"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/BlowOutInPlaceParams" + } + }, + "required": ["params"], + "title": "BlowOutInPlaceCreate", + "type": "object" + }, + "BlowOutInPlaceParams": { + "description": "Payload required to blow-out in place.", + "properties": { + "flowRate": { + "description": "Speed in \u00b5L/s configured for the pipette", + "exclusiveMinimum": 0.0, + "title": "Flowrate", + "type": "number" + }, + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + } + }, + "required": ["flowRate", "pipetteId"], + "title": "BlowOutInPlaceParams", + "type": "object" + }, + "BlowOutParams": { + "description": "Payload required to blow-out a specific well.", + "properties": { + "flowRate": { + "description": "Speed in \u00b5L/s configured for the pipette", + "exclusiveMinimum": 0.0, + "title": "Flowrate", + "type": "number" + }, + "labwareId": { + "description": "Identifier of labware to use.", + "title": "Labwareid", + "type": "string" + }, + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + }, + "wellLocation": { + "$ref": "#/$defs/WellLocation", + "description": "Relative well location at which to perform the operation" + }, + "wellName": { + "description": "Name of well to use in labware.", + "title": "Wellname", + "type": "string" + } + }, + "required": ["labwareId", "wellName", "flowRate", "pipetteId"], + "title": "BlowOutParams", + "type": "object" + }, + "BlowoutLocation": { + "description": "Location for blowout during a transfer function.", + "enum": ["source", "destination", "trash"], + "title": "BlowoutLocation", + "type": "string" + }, + "BlowoutParams": { + "description": "Parameters for blowout.", + "properties": { + "flowRate": { + "anyOf": [ + { + "minimum": 0, + "type": "integer" + }, + { + "minimum": 0.0, + "type": "number" + } + ], + "description": "Flow rate for blow out, in microliters per second.", + "title": "Flowrate" + }, + "location": { + "$ref": "#/$defs/BlowoutLocation", + "description": "Location well or trash entity for blow out." + } + }, + "required": ["location", "flowRate"], + "title": "BlowoutParams", + "type": "object" + }, + "BlowoutProperties": { + "description": "Blowout properties.", + "properties": { + "enable": { + "description": "Whether blow-out is enabled.", + "title": "Enable", + "type": "boolean" + }, + "params": { + "$ref": "#/$defs/BlowoutParams", + "description": "Parameters for the blowout function.", + "title": "Params" + } + }, + "required": ["enable"], + "title": "BlowoutProperties", + "type": "object" + }, + "CalibrateGripperCreate": { + "description": "A request to create a `calibrateGripper` command.", + "properties": { + "commandType": { + "const": "calibration/calibrateGripper", + "default": "calibration/calibrateGripper", + "enum": ["calibration/calibrateGripper"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/CalibrateGripperParams" + } + }, + "required": ["params"], + "title": "CalibrateGripperCreate", + "type": "object" + }, + "CalibrateGripperParams": { + "description": "Parameters for a `calibrateGripper` command.", + "properties": { + "jaw": { + "$ref": "#/$defs/CalibrateGripperParamsJaw", + "description": "Which of the gripper's jaws to use to measure its offset. The robot will assume that a human operator has already attached the capacitive probe to the jaw and none is attached to the other jaw." + }, + "otherJawOffset": { + "$ref": "#/$defs/Vec3f", + "description": "If an offset for the other probe is already found, then specifying it here will enable the CalibrateGripper command to complete the calibration process by calculating the total offset and saving it to disk. If this param is not specified then the command will only find and return the offset for the specified probe.", + "title": "Otherjawoffset" + } + }, + "required": ["jaw"], + "title": "CalibrateGripperParams", + "type": "object" + }, + "CalibrateGripperParamsJaw": { + "enum": ["front", "rear"], + "title": "CalibrateGripperParamsJaw", + "type": "string" + }, + "CalibrateModuleCreate": { + "description": "Create calibrate-module command request model.", + "properties": { + "commandType": { + "const": "calibration/calibrateModule", + "default": "calibration/calibrateModule", + "enum": ["calibration/calibrateModule"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/CalibrateModuleParams" + } + }, + "required": ["params"], + "title": "CalibrateModuleCreate", + "type": "object" + }, + "CalibrateModuleParams": { + "description": "Payload required to calibrate-module.", + "properties": { + "labwareId": { + "description": "The unique id of module calibration adapter labware.", + "title": "Labwareid", + "type": "string" + }, + "moduleId": { + "description": "The unique id of module to calibrate.", + "title": "Moduleid", + "type": "string" + }, + "mount": { + "$ref": "#/$defs/MountType", + "description": "The instrument mount used to calibrate the module." + } + }, + "required": ["moduleId", "labwareId", "mount"], + "title": "CalibrateModuleParams", + "type": "object" + }, + "CalibratePipetteCreate": { + "description": "Create calibrate-pipette command request model.", + "properties": { + "commandType": { + "const": "calibration/calibratePipette", + "default": "calibration/calibratePipette", + "enum": ["calibration/calibratePipette"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/CalibratePipetteParams" + } + }, + "required": ["params"], + "title": "CalibratePipetteCreate", + "type": "object" + }, + "CalibratePipetteParams": { + "description": "Payload required to calibrate-pipette.", + "properties": { + "mount": { + "$ref": "#/$defs/MountType", + "description": "Instrument mount to calibrate." + } + }, + "required": ["mount"], + "title": "CalibratePipetteParams", + "type": "object" + }, + "CloseLabwareLatchCreate": { + "description": "A request to create a Heater-Shaker's close latch command.", + "properties": { + "commandType": { + "const": "heaterShaker/closeLabwareLatch", + "default": "heaterShaker/closeLabwareLatch", + "enum": ["heaterShaker/closeLabwareLatch"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/CloseLabwareLatchParams" + } + }, + "required": ["params"], + "title": "CloseLabwareLatchCreate", + "type": "object" + }, + "CloseLabwareLatchParams": { + "description": "Input parameters to close a Heater-Shaker Module's labware latch.", + "properties": { + "moduleId": { + "description": "Unique ID of the Heater-Shaker Module.", + "title": "Moduleid", + "type": "string" + } + }, + "required": ["moduleId"], + "title": "CloseLabwareLatchParams", + "type": "object" + }, + "ColumnNozzleLayoutConfiguration": { + "description": "Information required for nozzle configurations of type ROW and COLUMN.", + "properties": { + "primaryNozzle": { + "description": "The primary nozzle to use in the layout configuration. This nozzle will update the critical point of the current pipette. For now, this is also the back left corner of your rectangle.", + "enum": ["A1", "H1", "A12", "H12"], + "title": "Primarynozzle", + "type": "string" + }, + "style": { + "const": "COLUMN", + "default": "COLUMN", + "enum": ["COLUMN"], + "title": "Style", + "type": "string" + } + }, + "required": ["primaryNozzle"], + "title": "ColumnNozzleLayoutConfiguration", + "type": "object" + }, + "CommandIntent": { + "description": "Run intent for a given command.\n\nProps:\n PROTOCOL: the command is part of the protocol run itself.\n SETUP: the command is part of the setup phase of a run.", + "enum": ["protocol", "setup", "fixit"], + "title": "CommandIntent", + "type": "string" + }, + "CommentCreate": { + "description": "Comment command request model.", + "properties": { + "commandType": { + "const": "comment", + "default": "comment", + "enum": ["comment"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/CommentParams" + } + }, + "required": ["params"], + "title": "CommentCreate", + "type": "object" + }, + "CommentParams": { + "description": "Payload required to annotate execution with a comment.", + "properties": { + "message": { + "description": "A user-facing message", + "title": "Message", + "type": "string" + } + }, + "required": ["message"], + "title": "CommentParams", + "type": "object" + }, + "ConfigureCreate": { + "description": "A request to execute a Flex Stacker Configure command.", + "properties": { + "commandType": { + "const": "flexStacker/configure", + "default": "flexStacker/configure", + "enum": ["flexStacker/configure"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/ConfigureParams" + } + }, + "required": ["params"], + "title": "ConfigureCreate", + "type": "object" + }, + "ConfigureForVolumeCreate": { + "description": "Configure for volume command creation request model.", + "properties": { + "commandType": { + "const": "configureForVolume", + "default": "configureForVolume", + "enum": ["configureForVolume"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/ConfigureForVolumeParams" + } + }, + "required": ["params"], + "title": "ConfigureForVolumeCreate", + "type": "object" + }, + "ConfigureForVolumeParams": { + "description": "Parameters required to configure volume for a specific pipette.", + "properties": { + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + }, + "tipOverlapNotAfterVersion": { + "description": "A version of tip overlap data to not exceed. The highest-versioned tip overlap data that does not exceed this version will be used. Versions are expressed as vN where N is an integer, counting up from v0. If None, the current highest version will be used.", + "title": "Tipoverlapnotafterversion", + "type": "string" + }, + "volume": { + "description": "Amount of liquid in uL. Must be at least 0 and no greater than a pipette-specific maximum volume.", + "minimum": 0.0, + "title": "Volume", + "type": "number" + } + }, + "required": ["pipetteId", "volume"], + "title": "ConfigureForVolumeParams", + "type": "object" + }, + "ConfigureNozzleLayoutCreate": { + "description": "Configure nozzle layout creation request model.", + "properties": { + "commandType": { + "const": "configureNozzleLayout", + "default": "configureNozzleLayout", + "enum": ["configureNozzleLayout"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/ConfigureNozzleLayoutParams" + } + }, + "required": ["params"], + "title": "ConfigureNozzleLayoutCreate", + "type": "object" + }, + "ConfigureNozzleLayoutParams": { + "description": "Parameters required to configure the nozzle layout for a specific pipette.", + "properties": { + "configurationParams": { + "anyOf": [ + { + "$ref": "#/$defs/AllNozzleLayoutConfiguration" + }, + { + "$ref": "#/$defs/SingleNozzleLayoutConfiguration" + }, + { + "$ref": "#/$defs/RowNozzleLayoutConfiguration" + }, + { + "$ref": "#/$defs/ColumnNozzleLayoutConfiguration" + }, + { + "$ref": "#/$defs/QuadrantNozzleLayoutConfiguration" + } + ], + "title": "Configurationparams" + }, + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + } + }, + "required": ["pipetteId", "configurationParams"], + "title": "ConfigureNozzleLayoutParams", + "type": "object" + }, + "ConfigureParams": { + "description": "Input parameters for a configure command.", + "properties": { + "moduleId": { + "description": "Unique ID of the Flex Stacker.", + "title": "Moduleid", + "type": "string" + }, + "static": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Whether the Flex Stacker should be in static mode.", + "title": "Static" + } + }, + "required": ["moduleId"], + "title": "ConfigureParams", + "type": "object" + }, + "Coordinate": { + "description": "Three-dimensional coordinates.", + "properties": { + "x": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "number" + } + ], + "title": "X" + }, + "y": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "number" + } + ], + "title": "Y" + }, + "z": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "number" + } + ], + "title": "Z" + } + }, + "required": ["x", "y", "z"], + "title": "Coordinate", + "type": "object" + }, + "CustomCreate": { + "description": "A request to create a custom command.", + "properties": { + "commandType": { + "const": "custom", + "default": "custom", + "enum": ["custom"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/CustomParams" + } + }, + "required": ["params"], + "title": "CustomCreate", + "type": "object" + }, + "CustomParams": { + "additionalProperties": true, + "description": "Payload used by a custom command.", + "properties": {}, + "title": "CustomParams", + "type": "object" + }, + "DeactivateBlockCreate": { + "description": "A request to create a Thermocycler's deactivate block command.", + "properties": { + "commandType": { + "const": "thermocycler/deactivateBlock", + "default": "thermocycler/deactivateBlock", + "enum": ["thermocycler/deactivateBlock"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/DeactivateBlockParams" + } + }, + "required": ["params"], + "title": "DeactivateBlockCreate", + "type": "object" + }, + "DeactivateBlockParams": { + "description": "Input parameters to unset a Thermocycler's target block temperature.", + "properties": { + "moduleId": { + "description": "Unique ID of the Thermocycler.", + "title": "Moduleid", + "type": "string" + } + }, + "required": ["moduleId"], + "title": "DeactivateBlockParams", + "type": "object" + }, + "DeactivateHeaterCreate": { + "description": "A request to create a Heater-Shaker's deactivate heater command.", + "properties": { + "commandType": { + "const": "heaterShaker/deactivateHeater", + "default": "heaterShaker/deactivateHeater", + "enum": ["heaterShaker/deactivateHeater"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/DeactivateHeaterParams" + } + }, + "required": ["params"], + "title": "DeactivateHeaterCreate", + "type": "object" + }, + "DeactivateHeaterParams": { + "description": "Input parameters to unset a Heater-Shaker's target temperature.", + "properties": { + "moduleId": { + "description": "Unique ID of the Heater-Shaker Module.", + "title": "Moduleid", + "type": "string" + } + }, + "required": ["moduleId"], + "title": "DeactivateHeaterParams", + "type": "object" + }, + "DeactivateLidCreate": { + "description": "A request to create a Thermocycler's deactivate lid command.", + "properties": { + "commandType": { + "const": "thermocycler/deactivateLid", + "default": "thermocycler/deactivateLid", + "enum": ["thermocycler/deactivateLid"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/DeactivateLidParams" + } + }, + "required": ["params"], + "title": "DeactivateLidCreate", + "type": "object" + }, + "DeactivateLidParams": { + "description": "Input parameters to unset a Thermocycler's target lid temperature.", + "properties": { + "moduleId": { + "description": "Unique ID of the Thermocycler.", + "title": "Moduleid", + "type": "string" + } + }, + "required": ["moduleId"], + "title": "DeactivateLidParams", + "type": "object" + }, + "DeactivateShakerCreate": { + "description": "A request to create a Heater-Shaker's deactivate shaker command.", + "properties": { + "commandType": { + "const": "heaterShaker/deactivateShaker", + "default": "heaterShaker/deactivateShaker", + "enum": ["heaterShaker/deactivateShaker"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/DeactivateShakerParams" + } + }, + "required": ["params"], + "title": "DeactivateShakerCreate", + "type": "object" + }, + "DeactivateShakerParams": { + "description": "Input parameters to deactivate shaker for a Heater-Shaker Module.", + "properties": { + "moduleId": { + "description": "Unique ID of the Heater-Shaker Module.", + "title": "Moduleid", + "type": "string" + } + }, + "required": ["moduleId"], + "title": "DeactivateShakerParams", + "type": "object" + }, + "DeactivateTemperatureCreate": { + "description": "A request to deactivate a Temperature Module.", + "properties": { + "commandType": { + "const": "temperatureModule/deactivate", + "default": "temperatureModule/deactivate", + "enum": ["temperatureModule/deactivate"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/DeactivateTemperatureParams" + } + }, + "required": ["params"], + "title": "DeactivateTemperatureCreate", + "type": "object" + }, + "DeactivateTemperatureParams": { + "description": "Input parameters to deactivate a Temperature Module.", + "properties": { + "moduleId": { + "description": "Unique ID of the Temperature Module.", + "title": "Moduleid", + "type": "string" + } + }, + "required": ["moduleId"], + "title": "DeactivateTemperatureParams", + "type": "object" + }, + "DeckPoint": { + "description": "Coordinates of a point in deck space.", + "properties": { + "x": { + "title": "X", + "type": "number" + }, + "y": { + "title": "Y", + "type": "number" + }, + "z": { + "title": "Z", + "type": "number" + } + }, + "required": ["x", "y", "z"], + "title": "DeckPoint", + "type": "object" + }, + "DeckSlotLocation": { + "description": "The location of something placed in a single deck slot.", + "properties": { + "slotName": { + "$ref": "#/$defs/DeckSlotName", + "description": "A slot on the robot's deck.\n\nThe plain numbers like `\"5\"` are for the OT-2, and the coordinates like `\"C2\"` are for the Flex.\n\nWhen you provide one of these values, you can use either style. It will automatically be converted to match the robot.\n\nWhen one of these values is returned, it will always match the robot." + } + }, + "required": ["slotName"], + "title": "DeckSlotLocation", + "type": "object" + }, + "DeckSlotName": { + "description": "Deck slot identifiers.", + "enum": [ + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "11", + "12", + "A1", + "A2", + "A3", + "B1", + "B2", + "B3", + "C1", + "C2", + "C3", + "D1", + "D2", + "D3" + ], + "title": "DeckSlotName", + "type": "string" + }, + "DelayParams": { + "description": "Parameters for delay.", + "properties": { + "duration": { + "anyOf": [ + { + "minimum": 0, + "type": "integer" + }, + { + "minimum": 0.0, + "type": "number" + } + ], + "description": "Duration of delay, in seconds.", + "title": "Duration" + } + }, + "required": ["duration"], + "title": "DelayParams", + "type": "object" + }, + "DelayProperties": { + "description": "Shared properties for delay..", + "properties": { + "enable": { + "description": "Whether delay is enabled.", + "title": "Enable", + "type": "boolean" + }, + "params": { + "$ref": "#/$defs/DelayParams", + "description": "Parameters for the delay function.", + "title": "Params" + } + }, + "required": ["enable"], + "title": "DelayProperties", + "type": "object" + }, + "DisengageCreate": { + "description": "A request to create a Magnetic Module disengage command.", + "properties": { + "commandType": { + "const": "magneticModule/disengage", + "default": "magneticModule/disengage", + "enum": ["magneticModule/disengage"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/DisengageParams" + } + }, + "required": ["params"], + "title": "DisengageCreate", + "type": "object" + }, + "DisengageParams": { + "description": "Input data to disengage a Magnetic Module's magnets.", + "properties": { + "moduleId": { + "description": "The ID of the Magnetic Module whose magnets you want to disengage, from a prior `loadModule` command.", + "title": "Moduleid", + "type": "string" + } + }, + "required": ["moduleId"], + "title": "DisengageParams", + "type": "object" + }, + "DispenseCreate": { + "description": "Create dispense command request model.", + "properties": { + "commandType": { + "const": "dispense", + "default": "dispense", + "enum": ["dispense"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/DispenseParams" + } + }, + "required": ["params"], + "title": "DispenseCreate", + "type": "object" + }, + "DispenseInPlaceCreate": { + "description": "DispenseInPlace command request model.", + "properties": { + "commandType": { + "const": "dispenseInPlace", + "default": "dispenseInPlace", + "enum": ["dispenseInPlace"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/DispenseInPlaceParams" + } + }, + "required": ["params"], + "title": "DispenseInPlaceCreate", + "type": "object" + }, + "DispenseInPlaceParams": { + "description": "Payload required to dispense in place.", + "properties": { + "correctionVolume": { + "anyOf": [ + { + "minimum": 0.0, + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The correction volume in uL.", + "title": "Correctionvolume" + }, + "flowRate": { + "description": "Speed in \u00b5L/s configured for the pipette", + "exclusiveMinimum": 0.0, + "title": "Flowrate", + "type": "number" + }, + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + }, + "pushOut": { + "description": "push the plunger a small amount farther than necessary for accurate low-volume dispensing", + "title": "Pushout", + "type": "number" + }, + "volume": { + "description": "The amount of liquid to dispense, in \u00b5L. Must not be greater than the currently aspirated volume. There is some tolerance for floating point rounding errors.", + "minimum": 0.0, + "title": "Volume", + "type": "number" + } + }, + "required": ["flowRate", "volume", "pipetteId"], + "title": "DispenseInPlaceParams", + "type": "object" + }, + "DispenseParams": { + "description": "Payload required to dispense to a specific well.", + "properties": { + "correctionVolume": { + "anyOf": [ + { + "minimum": 0.0, + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The correction volume in uL.", + "title": "Correctionvolume" + }, + "flowRate": { + "description": "Speed in \u00b5L/s configured for the pipette", + "exclusiveMinimum": 0.0, + "title": "Flowrate", + "type": "number" + }, + "labwareId": { + "description": "Identifier of labware to use.", + "title": "Labwareid", + "type": "string" + }, + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + }, + "pushOut": { + "description": "push the plunger a small amount farther than necessary for accurate low-volume dispensing", + "title": "Pushout", + "type": "number" + }, + "volume": { + "description": "The amount of liquid to dispense, in \u00b5L. Must not be greater than the currently aspirated volume. There is some tolerance for floating point rounding errors.", + "minimum": 0.0, + "title": "Volume", + "type": "number" + }, + "wellLocation": { + "$ref": "#/$defs/LiquidHandlingWellLocation", + "description": "Relative well location at which to perform the operation" + }, + "wellName": { + "description": "Name of well to use in labware.", + "title": "Wellname", + "type": "string" + } + }, + "required": ["labwareId", "wellName", "flowRate", "volume", "pipetteId"], + "title": "DispenseParams", + "type": "object" + }, + "DispenseWhileTrackingCreate": { + "description": "Create dispenseWhileTracking command request model.", + "properties": { + "commandType": { + "const": "dispenseWhileTracking", + "default": "dispenseWhileTracking", + "enum": ["dispenseWhileTracking"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/DispenseWhileTrackingParams" + } + }, + "required": ["params"], + "title": "DispenseWhileTrackingCreate", + "type": "object" + }, + "DispenseWhileTrackingParams": { + "description": "Payload required to dispense to a specific well.", + "properties": { + "correctionVolume": { + "anyOf": [ + { + "minimum": 0.0, + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The correction volume in uL.", + "title": "Correctionvolume" + }, + "flowRate": { + "description": "Speed in \u00b5L/s configured for the pipette", + "exclusiveMinimum": 0.0, + "title": "Flowrate", + "type": "number" + }, + "labwareId": { + "description": "Identifier of labware to use.", + "title": "Labwareid", + "type": "string" + }, + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + }, + "pushOut": { + "description": "push the plunger a small amount farther than necessary for accurate low-volume dispensing", + "title": "Pushout", + "type": "number" + }, + "volume": { + "description": "The amount of liquid to dispense, in \u00b5L. Must not be greater than the currently aspirated volume. There is some tolerance for floating point rounding errors.", + "minimum": 0.0, + "title": "Volume", + "type": "number" + }, + "wellLocation": { + "$ref": "#/$defs/LiquidHandlingWellLocation", + "description": "Relative well location at which to perform the operation" + }, + "wellName": { + "description": "Name of well to use in labware.", + "title": "Wellname", + "type": "string" + } + }, + "required": ["labwareId", "wellName", "flowRate", "volume", "pipetteId"], + "title": "DispenseWhileTrackingParams", + "type": "object" + }, + "DropTipCreate": { + "description": "Drop tip command creation request model.", + "properties": { + "commandType": { + "const": "dropTip", + "default": "dropTip", + "enum": ["dropTip"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/DropTipParams" + } + }, + "required": ["params"], + "title": "DropTipCreate", + "type": "object" + }, + "DropTipInPlaceCreate": { + "description": "Drop tip in place command creation request model.", + "properties": { + "commandType": { + "const": "dropTipInPlace", + "default": "dropTipInPlace", + "enum": ["dropTipInPlace"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/DropTipInPlaceParams" + } + }, + "required": ["params"], + "title": "DropTipInPlaceCreate", + "type": "object" + }, + "DropTipInPlaceParams": { + "description": "Payload required to drop a tip in place.", + "properties": { + "homeAfter": { + "description": "Whether to home this pipette's plunger after dropping the tip. You should normally leave this unspecified to let the robot choose a safe default depending on its hardware.", + "title": "Homeafter", + "type": "boolean" + }, + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + } + }, + "required": ["pipetteId"], + "title": "DropTipInPlaceParams", + "type": "object" + }, + "DropTipParams": { + "description": "Payload required to drop a tip in a specific well.", + "properties": { + "alternateDropLocation": { + "description": "Whether to alternate location where tip is dropped within the labware. If True, this command will ignore the wellLocation provided and alternate between dropping tips at two predetermined locations inside the specified labware well. If False, the tip will be dropped at the top center of the well.", + "title": "Alternatedroplocation", + "type": "boolean" + }, + "homeAfter": { + "description": "Whether to home this pipette's plunger after dropping the tip. You should normally leave this unspecified to let the robot choose a safe default depending on its hardware.", + "title": "Homeafter", + "type": "boolean" + }, + "labwareId": { + "description": "Identifier of labware to use.", + "title": "Labwareid", + "type": "string" + }, + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + }, + "wellLocation": { + "$ref": "#/$defs/DropTipWellLocation", + "description": "Relative well location at which to drop the tip." + }, + "wellName": { + "description": "Name of well to use in labware.", + "title": "Wellname", + "type": "string" + } + }, + "required": ["pipetteId", "labwareId", "wellName"], + "title": "DropTipParams", + "type": "object" + }, + "DropTipWellLocation": { + "description": "Like WellLocation, but for dropping tips.\n\nUnlike a typical WellLocation, the location for a drop tip\ndefaults to location based on the tip length rather than the well's top.", + "properties": { + "offset": { + "$ref": "#/$defs/WellOffset" + }, + "origin": { + "$ref": "#/$defs/DropTipWellOrigin", + "default": "default" + } + }, + "title": "DropTipWellLocation", + "type": "object" + }, + "DropTipWellOrigin": { + "description": "The origin of a DropTipWellLocation offset.\n\nProps:\n TOP: the top-center of the well\n BOTTOM: the bottom-center of the well\n CENTER: the middle-center of the well\n DEFAULT: the default drop-tip location of the well,\n based on pipette configuration and length of the tip.", + "enum": ["top", "bottom", "center", "default"], + "title": "DropTipWellOrigin", + "type": "string" + }, + "EngageCreate": { + "description": "A request to create a Magnetic Module engage command.", + "properties": { + "commandType": { + "const": "magneticModule/engage", + "default": "magneticModule/engage", + "enum": ["magneticModule/engage"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/EngageParams" + } + }, + "required": ["params"], + "title": "EngageCreate", + "type": "object" + }, + "EngageParams": { + "description": "Input data to engage a Magnetic Module.", + "properties": { + "height": { + "description": "How high, in millimeters, to raise the magnets.\n\nZero means the tops of the magnets are level with the ledge that the labware rests on. This will be slightly above the magnets' minimum height, the hardware home position. Negative values are allowed, to put the magnets below the ledge.\n\nUnits are always true millimeters. This is unlike certain labware definitions, engage commands in the Python Protocol API, and engage commands in older versions of the JSON protocol schema. Take care to convert properly.", + "title": "Height", + "type": "number" + }, + "moduleId": { + "description": "The ID of the Magnetic Module whose magnets you want to raise, from a prior `loadModule` command.", + "title": "Moduleid", + "type": "string" + } + }, + "required": ["moduleId", "height"], + "title": "EngageParams", + "type": "object" + }, + "GetNextTipCreate": { + "description": "Get next tip command creation request model.", + "properties": { + "commandType": { + "const": "getNextTip", + "default": "getNextTip", + "enum": ["getNextTip"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/GetNextTipParams" + } + }, + "required": ["params"], + "title": "GetNextTipCreate", + "type": "object" + }, + "GetNextTipParams": { + "description": "Payload needed to resolve the next available tip.", + "properties": { + "labwareIds": { + "description": "Labware ID(s) of tip racks to resolve next available tip(s) from Labware IDs will be resolved sequentially", + "items": { + "type": "string" + }, + "title": "Labwareids", + "type": "array" + }, + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + }, + "startingTipWell": { + "description": "Name of starting tip rack 'well'. This only applies to the first tip rack in the list provided in labwareIDs", + "title": "Startingtipwell", + "type": "string" + } + }, + "required": ["pipetteId", "labwareIds"], + "title": "GetNextTipParams", + "type": "object" + }, + "GetTipPresenceCreate": { + "description": "GetTipPresence command creation request model.", + "properties": { + "commandType": { + "const": "getTipPresence", + "default": "getTipPresence", + "enum": ["getTipPresence"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/GetTipPresenceParams" + } + }, + "required": ["params"], + "title": "GetTipPresenceCreate", + "type": "object" + }, + "GetTipPresenceParams": { + "description": "Payload required for a GetTipPresence command.", + "properties": { + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + } + }, + "required": ["pipetteId"], + "title": "GetTipPresenceParams", + "type": "object" + }, + "HomeCreate": { + "description": "Data to create a Home command.", + "properties": { + "commandType": { + "const": "home", + "default": "home", + "enum": ["home"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/HomeParams" + } + }, + "required": ["params"], + "title": "HomeCreate", + "type": "object" + }, + "HomeParams": { + "description": "Payload required for a Home command.", + "properties": { + "axes": { + "description": "Axes to return to their home positions. If omitted, will home all motors. Extra axes may be implicitly homed to ensure accurate homing of the explicitly specified axes.", + "items": { + "$ref": "#/$defs/MotorAxis" + }, + "title": "Axes", + "type": "array" + }, + "skipIfMountPositionOk": { + "$ref": "#/$defs/MountType", + "description": "If this parameter is provided, the gantry will only be homed if the specified mount has an invalid position. If omitted, the homing action will be executed unconditionally.", + "title": "Skipifmountpositionok" + } + }, + "title": "HomeParams", + "type": "object" + }, + "InitializeCreate": { + "description": "A request to execute an Absorbance Reader measurement.", + "properties": { + "commandType": { + "const": "absorbanceReader/initialize", + "default": "absorbanceReader/initialize", + "enum": ["absorbanceReader/initialize"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/InitializeParams" + } + }, + "required": ["params"], + "title": "InitializeCreate", + "type": "object" + }, + "InitializeParams": { + "description": "Input parameters to initialize an absorbance reading.", + "properties": { + "measureMode": { + "description": "Initialize single or multi measurement mode.", + "enum": ["single", "multi"], + "title": "Measuremode", + "type": "string" + }, + "moduleId": { + "description": "Unique ID of the absorbance reader.", + "title": "Moduleid", + "type": "string" + }, + "referenceWavelength": { + "description": "Optional reference wavelength in nm.", + "title": "Referencewavelength", + "type": "integer" + }, + "sampleWavelengths": { + "description": "Sample wavelengths in nm.", + "items": { + "type": "integer" + }, + "title": "Samplewavelengths", + "type": "array" + } + }, + "required": ["moduleId", "measureMode", "sampleWavelengths"], + "title": "InitializeParams", + "type": "object" + }, + "InstrumentSensorId": { + "description": "Primary and secondary sensor ids.", + "enum": ["primary", "secondary", "both"], + "title": "InstrumentSensorId", + "type": "string" + }, + "LabwareMovementStrategy": { + "description": "Strategy to use for labware movement.", + "enum": ["usingGripper", "manualMoveWithPause", "manualMoveWithoutPause"], + "title": "LabwareMovementStrategy", + "type": "string" + }, + "LabwareOffsetVector": { + "description": "Offset, in deck coordinates from nominal to actual position.", + "properties": { + "x": { + "title": "X", + "type": "number" + }, + "y": { + "title": "Y", + "type": "number" + }, + "z": { + "title": "Z", + "type": "number" + } + }, + "required": ["x", "y", "z"], + "title": "LabwareOffsetVector", + "type": "object" + }, + "LiquidClassRecord": { + "description": "LiquidClassRecord is our internal representation of an (immutable) liquid class.\n\nConceptually, a liquid class record is the tuple (name, pipette, tip, transfer properties).\nWe consider two liquid classes to be the same if every entry in that tuple is the same; and liquid\nclasses are different if any entry in the tuple is different.\n\nThis class defines the tuple via inheritance so that we can reuse the definitions from shared_data.", + "properties": { + "aspirate": { + "$ref": "#/$defs/AspirateProperties", + "description": "Aspirate parameters for this tip type." + }, + "liquidClassName": { + "description": "Identifier for the liquid of this liquid class, e.g. glycerol50.", + "title": "Liquidclassname", + "type": "string" + }, + "multiDispense": { + "$ref": "#/$defs/MultiDispenseProperties", + "description": "Optional multi-dispense parameters for this tip type.", + "title": "Multidispense" + }, + "pipetteModel": { + "description": "Identifier for the pipette of this liquid class.", + "title": "Pipettemodel", + "type": "string" + }, + "singleDispense": { + "$ref": "#/$defs/SingleDispenseProperties", + "description": "Single dispense parameters for this tip type." + }, + "tiprack": { + "description": "The name of tiprack whose tip will be used when handling this specific liquid class with this pipette", + "title": "Tiprack", + "type": "string" + } + }, + "required": [ + "tiprack", + "aspirate", + "singleDispense", + "liquidClassName", + "pipetteModel" + ], + "title": "LiquidClassRecord", + "type": "object" + }, + "LiquidClassTouchTipParams": { + "description": "Parameters for touch-tip.", + "properties": { + "mmToEdge": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "number" + } + ], + "description": "Offset away from the the well edge, in millimeters.", + "title": "Mmtoedge" + }, + "speed": { + "anyOf": [ + { + "minimum": 0, + "type": "integer" + }, + { + "minimum": 0.0, + "type": "number" + } + ], + "description": "Touch-tip speed, in millimeters per second.", + "title": "Speed" + }, + "zOffset": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "number" + } + ], + "description": "Offset from the top of the well for touch-tip, in millimeters.", + "title": "Zoffset" + } + }, + "required": ["zOffset", "mmToEdge", "speed"], + "title": "LiquidClassTouchTipParams", + "type": "object" + }, + "LiquidHandlingWellLocation": { + "description": "A relative location in reference to a well's location.\n\nTo be used with commands that handle liquids.", + "properties": { + "offset": { + "$ref": "#/$defs/WellOffset" + }, + "origin": { + "$ref": "#/$defs/WellOrigin", + "default": "top" + }, + "volumeOffset": { + "anyOf": [ + { + "type": "number" + }, + { + "const": "operationVolume", + "enum": ["operationVolume"], + "type": "string" + } + ], + "default": 0.0, + "description": "A volume of liquid, in \u00b5L, to offset the z-axis offset. When \"operationVolume\" is specified, this volume is pulled from the command volume parameter.", + "title": "Volumeoffset" + } + }, + "title": "LiquidHandlingWellLocation", + "type": "object" + }, + "LiquidProbeCreate": { + "description": "The request model for a `liquidProbe` command.", + "properties": { + "commandType": { + "const": "liquidProbe", + "default": "liquidProbe", + "enum": ["liquidProbe"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/LiquidProbeParams" + } + }, + "required": ["params"], + "title": "LiquidProbeCreate", + "type": "object" + }, + "LiquidProbeParams": { + "description": "Parameters required for a `liquidProbe` command.", + "properties": { + "labwareId": { + "description": "Identifier of labware to use.", + "title": "Labwareid", + "type": "string" + }, + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + }, + "wellLocation": { + "$ref": "#/$defs/WellLocation", + "description": "Relative well location at which to perform the operation" + }, + "wellName": { + "description": "Name of well to use in labware.", + "title": "Wellname", + "type": "string" + } + }, + "required": ["labwareId", "wellName", "pipetteId"], + "title": "LiquidProbeParams", + "type": "object" + }, + "LoadLabwareCreate": { + "description": "Load labware command creation request.", + "properties": { + "commandType": { + "const": "loadLabware", + "default": "loadLabware", + "enum": ["loadLabware"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/LoadLabwareParams" + } + }, + "required": ["params"], + "title": "LoadLabwareCreate", + "type": "object" + }, + "LoadLabwareParams": { + "description": "Payload required to load a labware into a slot.", + "properties": { + "displayName": { + "description": "An optional user-specified display name or label for this labware.", + "title": "Displayname", + "type": "string" + }, + "labwareId": { + "description": "An optional ID to assign to this labware. If None, an ID will be generated.", + "title": "Labwareid", + "type": "string" + }, + "loadName": { + "description": "Name used to reference a labware definition.", + "title": "Loadname", + "type": "string" + }, + "location": { + "anyOf": [ + { + "$ref": "#/$defs/DeckSlotLocation" + }, + { + "$ref": "#/$defs/ModuleLocation" + }, + { + "$ref": "#/$defs/OnLabwareLocation" + }, + { + "const": "offDeck", + "enum": ["offDeck"], + "type": "string" + }, + { + "const": "systemLocation", + "enum": ["systemLocation"], + "type": "string" + }, + { + "$ref": "#/$defs/AddressableAreaLocation" + } + ], + "description": "Location the labware should be loaded into.", + "title": "Location" + }, + "namespace": { + "description": "The namespace the labware definition belongs to.", + "title": "Namespace", + "type": "string" + }, + "version": { + "description": "The labware definition version.", + "title": "Version", + "type": "integer" + } + }, + "required": ["location", "loadName", "namespace", "version"], + "title": "LoadLabwareParams", + "type": "object" + }, + "LoadLidCreate": { + "description": "Load lid command creation request.", + "properties": { + "commandType": { + "const": "loadLid", + "default": "loadLid", + "enum": ["loadLid"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/LoadLidParams" + } + }, + "required": ["params"], + "title": "LoadLidCreate", + "type": "object" + }, + "LoadLidParams": { + "description": "Payload required to load a lid onto a labware.", + "properties": { + "loadName": { + "description": "Name used to reference a lid labware definition.", + "title": "Loadname", + "type": "string" + }, + "location": { + "anyOf": [ + { + "$ref": "#/$defs/DeckSlotLocation" + }, + { + "$ref": "#/$defs/ModuleLocation" + }, + { + "$ref": "#/$defs/OnLabwareLocation" + }, + { + "const": "offDeck", + "enum": ["offDeck"], + "type": "string" + }, + { + "const": "systemLocation", + "enum": ["systemLocation"], + "type": "string" + }, + { + "$ref": "#/$defs/AddressableAreaLocation" + } + ], + "description": "Labware the lid should be loaded onto.", + "title": "Location" + }, + "namespace": { + "description": "The namespace the lid labware definition belongs to.", + "title": "Namespace", + "type": "string" + }, + "version": { + "description": "The lid labware definition version.", + "title": "Version", + "type": "integer" + } + }, + "required": ["location", "loadName", "namespace", "version"], + "title": "LoadLidParams", + "type": "object" + }, + "LoadLidStackCreate": { + "description": "Load lid stack command creation request.", + "properties": { + "commandType": { + "const": "loadLidStack", + "default": "loadLidStack", + "enum": ["loadLidStack"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/LoadLidStackParams" + } + }, + "required": ["params"], + "title": "LoadLidStackCreate", + "type": "object" + }, + "LoadLidStackParams": { + "description": "Payload required to load a lid stack onto a location.", + "properties": { + "labwareIds": { + "description": "An optional list of IDs to assign to the lids in the stack.If None, an ID will be generated.", + "items": { + "type": "string" + }, + "title": "Labwareids", + "type": "array" + }, + "loadName": { + "description": "Name used to reference a lid labware definition.", + "title": "Loadname", + "type": "string" + }, + "location": { + "anyOf": [ + { + "$ref": "#/$defs/DeckSlotLocation" + }, + { + "$ref": "#/$defs/ModuleLocation" + }, + { + "$ref": "#/$defs/OnLabwareLocation" + }, + { + "const": "offDeck", + "enum": ["offDeck"], + "type": "string" + }, + { + "const": "systemLocation", + "enum": ["systemLocation"], + "type": "string" + }, + { + "$ref": "#/$defs/AddressableAreaLocation" + } + ], + "description": "Location the lid stack should be loaded into.", + "title": "Location" + }, + "namespace": { + "description": "The namespace the lid labware definition belongs to.", + "title": "Namespace", + "type": "string" + }, + "quantity": { + "description": "The quantity of lids to load.", + "title": "Quantity", + "type": "integer" + }, + "stackLabwareId": { + "description": "An optional ID to assign to the lid stack labware object created.If None, an ID will be generated.", + "title": "Stacklabwareid", + "type": "string" + }, + "version": { + "description": "The lid labware definition version.", + "title": "Version", + "type": "integer" + } + }, + "required": ["location", "loadName", "namespace", "version", "quantity"], + "title": "LoadLidStackParams", + "type": "object" + }, + "LoadLiquidClassCreate": { + "description": "Load Liquid Class command creation request.", + "properties": { + "commandType": { + "const": "loadLiquidClass", + "default": "loadLiquidClass", + "enum": ["loadLiquidClass"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/LoadLiquidClassParams" + } + }, + "required": ["params"], + "title": "LoadLiquidClassCreate", + "type": "object" + }, + "LoadLiquidClassParams": { + "description": "The liquid class transfer properties to store.", + "properties": { + "liquidClassId": { + "description": "Unique identifier for the liquid class to store. If you do not supply a liquidClassId, we will generate one.", + "title": "Liquidclassid", + "type": "string" + }, + "liquidClassRecord": { + "$ref": "#/$defs/LiquidClassRecord", + "description": "The liquid class to store." + } + }, + "required": ["liquidClassRecord"], + "title": "LoadLiquidClassParams", + "type": "object" + }, + "LoadLiquidCreate": { + "description": "Load liquid command creation request.", + "properties": { + "commandType": { + "const": "loadLiquid", + "default": "loadLiquid", + "enum": ["loadLiquid"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/LoadLiquidParams" + } + }, + "required": ["params"], + "title": "LoadLiquidCreate", + "type": "object" + }, + "LoadLiquidParams": { + "description": "Payload required to load a liquid into a well.", + "properties": { + "labwareId": { + "description": "Unique identifier of labware to load liquid into.", + "title": "Labwareid", + "type": "string" + }, + "liquidId": { + "anyOf": [ + { + "type": "string" + }, + { + "const": "EMPTY", + "enum": ["EMPTY"], + "type": "string" + } + ], + "description": "Unique identifier of the liquid to load. If this is the sentinel value EMPTY, all values of volumeByWell must be 0.", + "title": "Liquidid" + }, + "volumeByWell": { + "additionalProperties": { + "type": "number" + }, + "description": "Volume of liquid, in \u00b5L, loaded into each well by name, in this labware. If the liquid id is the sentinel value EMPTY, all volumes must be 0.", + "title": "Volumebywell", + "type": "object" + } + }, + "required": ["liquidId", "labwareId", "volumeByWell"], + "title": "LoadLiquidParams", + "type": "object" + }, + "LoadModuleCreate": { + "description": "The model for a creation request for a load module command.", + "properties": { + "commandType": { + "const": "loadModule", + "default": "loadModule", + "enum": ["loadModule"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/LoadModuleParams" + } + }, + "required": ["params"], + "title": "LoadModuleCreate", + "type": "object" + }, + "LoadModuleParams": { + "description": "Payload required to load a module.", + "properties": { + "location": { + "$ref": "#/$defs/DeckSlotLocation", + "description": "The location into which this module should be loaded.\n\nFor the Thermocycler Module, which occupies multiple deck slots, this should be the front-most occupied slot (normally slot 7)." + }, + "model": { + "$ref": "#/$defs/ModuleModel", + "description": "The model name of the module to load.\n\nProtocol Engine will look for a connected module that either exactly matches this one, or is compatible.\n\n For example, if you request a `temperatureModuleV1` here, Protocol Engine might load a `temperatureModuleV1` or a `temperatureModuleV2`.\n\n The model that it finds connected will be available through `result.model`." + }, + "moduleId": { + "description": "An optional ID to assign to this module. If None, an ID will be generated.", + "title": "Moduleid", + "type": "string" + } + }, + "required": ["model", "location"], + "title": "LoadModuleParams", + "type": "object" + }, + "LoadPipetteCreate": { + "description": "Load pipette command creation request model.", + "properties": { + "commandType": { + "const": "loadPipette", + "default": "loadPipette", + "enum": ["loadPipette"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/LoadPipetteParams" + } + }, + "required": ["params"], + "title": "LoadPipetteCreate", + "type": "object" + }, + "LoadPipetteParams": { + "description": "Payload needed to load a pipette on to a mount.", + "properties": { + "liquidPresenceDetection": { + "description": "Enable liquid presence detection for this pipette. Defaults to False.", + "title": "Liquidpresencedetection", + "type": "boolean" + }, + "mount": { + "$ref": "#/$defs/MountType", + "description": "The mount the pipette should be present on." + }, + "pipetteId": { + "description": "An optional ID to assign to this pipette. If None, an ID will be generated.", + "title": "Pipetteid", + "type": "string" + }, + "pipetteName": { + "$ref": "#/$defs/PipetteNameType", + "description": "The load name of the pipette to be required." + }, + "tipOverlapNotAfterVersion": { + "description": "A version of tip overlap data to not exceed. The highest-versioned tip overlap data that does not exceed this version will be used. Versions are expressed as vN where N is an integer, counting up from v0. If None, the current highest version will be used.", + "title": "Tipoverlapnotafterversion", + "type": "string" + } + }, + "required": ["pipetteName", "mount"], + "title": "LoadPipetteParams", + "type": "object" + }, + "MaintenancePosition": { + "description": "Maintenance position options.", + "enum": ["attachPlate", "attachInstrument"], + "title": "MaintenancePosition", + "type": "string" + }, + "MixParams": { + "description": "Parameters for mix.", + "properties": { + "repetitions": { + "description": "Number of mixing repetitions.", + "minimum": 0, + "title": "Repetitions", + "type": "integer" + }, + "volume": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "number" + } + ], + "description": "Volume used for mixing, in microliters.", + "title": "Volume" + } + }, + "required": ["repetitions", "volume"], + "title": "MixParams", + "type": "object" + }, + "MixProperties": { + "description": "Mixing properties.", + "properties": { + "enable": { + "description": "Whether mix is enabled.", + "title": "Enable", + "type": "boolean" + }, + "params": { + "$ref": "#/$defs/MixParams", + "description": "Parameters for the mix function.", + "title": "Params" + } + }, + "required": ["enable"], + "title": "MixProperties", + "type": "object" + }, + "ModuleLocation": { + "description": "The location of something placed atop a hardware module.", + "properties": { + "moduleId": { + "description": "The ID of a loaded module from a prior `loadModule` command.", + "title": "Moduleid", + "type": "string" + } + }, + "required": ["moduleId"], + "title": "ModuleLocation", + "type": "object" + }, + "ModuleModel": { + "description": "All available modules' models.", + "enum": [ + "temperatureModuleV1", + "temperatureModuleV2", + "magneticModuleV1", + "magneticModuleV2", + "thermocyclerModuleV1", + "thermocyclerModuleV2", + "heaterShakerModuleV1", + "magneticBlockV1", + "absorbanceReaderV1", + "flexStackerModuleV1" + ], + "title": "ModuleModel", + "type": "string" + }, + "MotorAxis": { + "description": "Motor axis on which to issue a home command.", + "enum": [ + "x", + "y", + "leftZ", + "rightZ", + "leftPlunger", + "rightPlunger", + "extensionZ", + "extensionJaw", + "axis96ChannelCam" + ], + "title": "MotorAxis", + "type": "string" + }, + "MountType": { + "enum": ["left", "right", "extension"], + "title": "MountType", + "type": "string" + }, + "MoveAxesRelativeCreate": { + "description": "MoveAxesRelative command request model.", + "properties": { + "commandType": { + "const": "robot/moveAxesRelative", + "default": "robot/moveAxesRelative", + "enum": ["robot/moveAxesRelative"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/MoveAxesRelativeParams" + } + }, + "required": ["params"], + "title": "MoveAxesRelativeCreate", + "type": "object" + }, + "MoveAxesRelativeParams": { + "description": "Payload required to move axes relative to position.", + "properties": { + "axis_map": { + "additionalProperties": { + "type": "number" + }, + "description": "A dictionary mapping axes to relative movements in mm.", + "title": "Axis Map", + "type": "object" + }, + "speed": { + "description": "The max velocity to move the axes at. Will fall to hardware defaults if none provided.", + "title": "Speed", + "type": "number" + } + }, + "required": ["axis_map"], + "title": "MoveAxesRelativeParams", + "type": "object" + }, + "MoveAxesToCreate": { + "description": "MoveAxesTo command request model.", + "properties": { + "commandType": { + "const": "robot/moveAxesTo", + "default": "robot/moveAxesTo", + "enum": ["robot/moveAxesTo"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/MoveAxesToParams" + } + }, + "required": ["params"], + "title": "MoveAxesToCreate", + "type": "object" + }, + "MoveAxesToParams": { + "description": "Payload required to move axes to absolute position.", + "properties": { + "axis_map": { + "additionalProperties": { + "type": "number" + }, + "description": "The specified axes to move to an absolute deck position with.", + "title": "Axis Map", + "type": "object" + }, + "critical_point": { + "additionalProperties": { + "type": "number" + }, + "description": "The critical point to move the mount with.", + "title": "Critical Point", + "type": "object" + }, + "speed": { + "description": "The max velocity to move the axes at. Will fall to hardware defaults if none provided.", + "title": "Speed", + "type": "number" + } + }, + "required": ["axis_map"], + "title": "MoveAxesToParams", + "type": "object" + }, + "MoveLabwareCreate": { + "description": "A request to create a ``moveLabware`` command.", + "properties": { + "commandType": { + "const": "moveLabware", + "default": "moveLabware", + "enum": ["moveLabware"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/MoveLabwareParams" + } + }, + "required": ["params"], + "title": "MoveLabwareCreate", + "type": "object" + }, + "MoveLabwareParams": { + "description": "Input parameters for a ``moveLabware`` command.", + "properties": { + "dropOffset": { + "$ref": "#/$defs/LabwareOffsetVector", + "description": "Offset to use when dropping off labware. Experimental param, subject to change", + "title": "Dropoffset" + }, + "labwareId": { + "description": "The ID of the labware to move.", + "title": "Labwareid", + "type": "string" + }, + "newLocation": { + "anyOf": [ + { + "$ref": "#/$defs/DeckSlotLocation" + }, + { + "$ref": "#/$defs/ModuleLocation" + }, + { + "$ref": "#/$defs/OnLabwareLocation" + }, + { + "const": "offDeck", + "enum": ["offDeck"], + "type": "string" + }, + { + "const": "systemLocation", + "enum": ["systemLocation"], + "type": "string" + }, + { + "$ref": "#/$defs/AddressableAreaLocation" + } + ], + "description": "Where to move the labware.", + "title": "Newlocation" + }, + "pickUpOffset": { + "$ref": "#/$defs/LabwareOffsetVector", + "description": "Offset to use when picking up labware. Experimental param, subject to change", + "title": "Pickupoffset" + }, + "strategy": { + "$ref": "#/$defs/LabwareMovementStrategy", + "description": "Whether to use the gripper to perform the labware movement or to perform a manual movement with an option to pause." + } + }, + "required": ["labwareId", "newLocation", "strategy"], + "title": "MoveLabwareParams", + "type": "object" + }, + "MoveRelativeCreate": { + "description": "Data to create a MoveRelative command.", + "properties": { + "commandType": { + "const": "moveRelative", + "default": "moveRelative", + "enum": ["moveRelative"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/MoveRelativeParams" + } + }, + "required": ["params"], + "title": "MoveRelativeCreate", + "type": "object" + }, + "MoveRelativeParams": { + "description": "Payload required for a MoveRelative command.", + "properties": { + "axis": { + "$ref": "#/$defs/MovementAxis", + "description": "Axis along which to move." + }, + "distance": { + "description": "Distance to move in millimeters. A positive number will move towards the right (x), back (y), top (z) of the deck.", + "title": "Distance", + "type": "number" + }, + "pipetteId": { + "description": "Pipette to move.", + "title": "Pipetteid", + "type": "string" + } + }, + "required": ["pipetteId", "axis", "distance"], + "title": "MoveRelativeParams", + "type": "object" + }, + "MoveToAddressableAreaCreate": { + "description": "Move to addressable area command creation request model.", + "properties": { + "commandType": { + "const": "moveToAddressableArea", + "default": "moveToAddressableArea", + "enum": ["moveToAddressableArea"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/MoveToAddressableAreaParams" + } + }, + "required": ["params"], + "title": "MoveToAddressableAreaCreate", + "type": "object" + }, + "MoveToAddressableAreaForDropTipCreate": { + "description": "Move to addressable area for drop tip command creation request model.", + "properties": { + "commandType": { + "const": "moveToAddressableAreaForDropTip", + "default": "moveToAddressableAreaForDropTip", + "enum": ["moveToAddressableAreaForDropTip"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/MoveToAddressableAreaForDropTipParams" + } + }, + "required": ["params"], + "title": "MoveToAddressableAreaForDropTipCreate", + "type": "object" + }, + "MoveToAddressableAreaForDropTipParams": { + "description": "Payload required to move a pipette to a specific addressable area.\n\nAn *addressable area* is a space in the robot that may or may not be usable depending on how\nthe robot's deck is configured. For example, if a Flex is configured with a waste chute, it will\nhave additional addressable areas representing the opening of the waste chute, where tips and\nlabware can be dropped.\n\nThis moves the pipette so all of its nozzles are centered over the addressable area.\nIf the pipette is currently configured with a partial tip layout, this centering is over all\nthe pipette's physical nozzles, not just the nozzles that are active.\n\nThe z-position will be chosen to put the bottom of the tips---or the bottom of the nozzles,\nif there are no tips---level with the top of the addressable area.\n\nWhen this command is executed, Protocol Engine will make sure the robot's deck is configured\nsuch that the requested addressable area actually exists. For example, if you request\nthe addressable area B4, it will make sure the robot is set up with a B3/B4 staging area slot.\nIf that's not the case, the command will fail.", + "properties": { + "addressableAreaName": { + "description": "The name of the addressable area that you want to use. Valid values are the `id`s of `addressableArea`s in the [deck definition](https://github.com/Opentrons/opentrons/tree/edge/shared-data/deck).", + "title": "Addressableareaname", + "type": "string" + }, + "alternateDropLocation": { + "description": "Whether to alternate location where tip is dropped within the addressable area. If True, this command will ignore the offset provided and alternate between dropping tips at two predetermined locations inside the specified labware well. If False, the tip will be dropped at the top center of the area.", + "title": "Alternatedroplocation", + "type": "boolean" + }, + "forceDirect": { + "default": false, + "description": "If true, moving from one labware/well to another will not arc to the default safe z, but instead will move directly to the specified location. This will also force the `minimumZHeight` param to be ignored. A 'direct' movement is in X/Y/Z simultaneously.", + "title": "Forcedirect", + "type": "boolean" + }, + "ignoreTipConfiguration": { + "description": "Whether to utilize the critical point of the tip configuraiton when moving to an addressable area. If True, this command will ignore the tip configuration and use the center of the entire instrument as the critical point for movement. If False, this command will use the critical point provided by the current tip configuration.", + "title": "Ignoretipconfiguration", + "type": "boolean" + }, + "minimumZHeight": { + "description": "Optional minimal Z margin in mm. If this is larger than the API's default safe Z margin, it will make the arc higher. If it's smaller, it will have no effect.", + "title": "Minimumzheight", + "type": "number" + }, + "offset": { + "$ref": "#/$defs/AddressableOffsetVector", + "default": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "description": "Relative offset of addressable area to move pipette's critical point." + }, + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + }, + "speed": { + "description": "Override the travel speed in mm/s. This controls the straight linear speed of motion.", + "title": "Speed", + "type": "number" + } + }, + "required": ["pipetteId", "addressableAreaName"], + "title": "MoveToAddressableAreaForDropTipParams", + "type": "object" + }, + "MoveToAddressableAreaParams": { + "description": "Payload required to move a pipette to a specific addressable area.\n\nAn *addressable area* is a space in the robot that may or may not be usable depending on how\nthe robot's deck is configured. For example, if a Flex is configured with a waste chute, it will\nhave additional addressable areas representing the opening of the waste chute, where tips and\nlabware can be dropped.\n\nThis moves the pipette so all of its nozzles are centered over the addressable area.\nIf the pipette is currently configured with a partial tip layout, this centering is over all\nthe pipette's physical nozzles, not just the nozzles that are active.\n\nThe z-position will be chosen to put the bottom of the tips---or the bottom of the nozzles,\nif there are no tips---level with the top of the addressable area.\n\nWhen this command is executed, Protocol Engine will make sure the robot's deck is configured\nsuch that the requested addressable area actually exists. For example, if you request\nthe addressable area B4, it will make sure the robot is set up with a B3/B4 staging area slot.\nIf that's not the case, the command will fail.", + "properties": { + "addressableAreaName": { + "description": "The name of the addressable area that you want to use. Valid values are the `id`s of `addressableArea`s in the [deck definition](https://github.com/Opentrons/opentrons/tree/edge/shared-data/deck).", + "title": "Addressableareaname", + "type": "string" + }, + "forceDirect": { + "default": false, + "description": "If true, moving from one labware/well to another will not arc to the default safe z, but instead will move directly to the specified location. This will also force the `minimumZHeight` param to be ignored. A 'direct' movement is in X/Y/Z simultaneously.", + "title": "Forcedirect", + "type": "boolean" + }, + "minimumZHeight": { + "description": "Optional minimal Z margin in mm. If this is larger than the API's default safe Z margin, it will make the arc higher. If it's smaller, it will have no effect.", + "title": "Minimumzheight", + "type": "number" + }, + "offset": { + "$ref": "#/$defs/AddressableOffsetVector", + "default": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "description": "Relative offset of addressable area to move pipette's critical point." + }, + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + }, + "speed": { + "description": "Override the travel speed in mm/s. This controls the straight linear speed of motion.", + "title": "Speed", + "type": "number" + }, + "stayAtHighestPossibleZ": { + "default": false, + "description": "If `true`, the pipette will retract to its highest possible height and stay there instead of descending to the destination. `minimumZHeight` will be ignored.", + "title": "Stayathighestpossiblez", + "type": "boolean" + } + }, + "required": ["pipetteId", "addressableAreaName"], + "title": "MoveToAddressableAreaParams", + "type": "object" + }, + "MoveToCoordinatesCreate": { + "description": "Move to coordinates command creation request model.", + "properties": { + "commandType": { + "const": "moveToCoordinates", + "default": "moveToCoordinates", + "enum": ["moveToCoordinates"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/MoveToCoordinatesParams" + } + }, + "required": ["params"], + "title": "MoveToCoordinatesCreate", + "type": "object" + }, + "MoveToCoordinatesParams": { + "description": "Payload required to move a pipette to coordinates.", + "properties": { + "coordinates": { + "$ref": "#/$defs/DeckPoint", + "description": "X, Y and Z coordinates in mm from deck's origin location (left-front-bottom corner of work space)" + }, + "forceDirect": { + "default": false, + "description": "If true, moving from one labware/well to another will not arc to the default safe z, but instead will move directly to the specified location. This will also force the `minimumZHeight` param to be ignored. A 'direct' movement is in X/Y/Z simultaneously.", + "title": "Forcedirect", + "type": "boolean" + }, + "minimumZHeight": { + "description": "Optional minimal Z margin in mm. If this is larger than the API's default safe Z margin, it will make the arc higher. If it's smaller, it will have no effect.", + "title": "Minimumzheight", + "type": "number" + }, + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + }, + "speed": { + "description": "Override the travel speed in mm/s. This controls the straight linear speed of motion.", + "title": "Speed", + "type": "number" + } + }, + "required": ["pipetteId", "coordinates"], + "title": "MoveToCoordinatesParams", + "type": "object" + }, + "MoveToCreate": { + "description": "MoveTo command request model.", + "properties": { + "commandType": { + "const": "robot/moveTo", + "default": "robot/moveTo", + "enum": ["robot/moveTo"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/MoveToParams" + } + }, + "required": ["params"], + "title": "MoveToCreate", + "type": "object" + }, + "MoveToMaintenancePositionCreate": { + "description": "Calibration set up position command creation request model.", + "properties": { + "commandType": { + "const": "calibration/moveToMaintenancePosition", + "default": "calibration/moveToMaintenancePosition", + "enum": ["calibration/moveToMaintenancePosition"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/MoveToMaintenancePositionParams" + } + }, + "required": ["params"], + "title": "MoveToMaintenancePositionCreate", + "type": "object" + }, + "MoveToMaintenancePositionParams": { + "description": "Calibration set up position command parameters.", + "properties": { + "maintenancePosition": { + "$ref": "#/$defs/MaintenancePosition", + "default": "attachInstrument", + "description": "The position the gantry mount needs to move to." + }, + "mount": { + "$ref": "#/$defs/MountType", + "description": "Gantry mount to move maintenance position." + } + }, + "required": ["mount"], + "title": "MoveToMaintenancePositionParams", + "type": "object" + }, + "MoveToParams": { + "description": "Payload required to move to a destination position.", + "properties": { + "destination": { + "$ref": "#/$defs/DeckPoint", + "description": "X, Y and Z coordinates in mm from deck's origin location (left-front-bottom corner of work space)" + }, + "mount": { + "$ref": "#/$defs/MountType", + "description": "The mount to move to the destination point." + }, + "speed": { + "description": "The max velocity to move the axes at. Will fall to hardware defaults if none provided.", + "title": "Speed", + "type": "number" + } + }, + "required": ["mount", "destination"], + "title": "MoveToParams", + "type": "object" + }, + "MoveToWellCreate": { + "description": "Move to well command creation request model.", + "properties": { + "commandType": { + "const": "moveToWell", + "default": "moveToWell", + "enum": ["moveToWell"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/MoveToWellParams" + } + }, + "required": ["params"], + "title": "MoveToWellCreate", + "type": "object" + }, + "MoveToWellParams": { + "description": "Payload required to move a pipette to a specific well.", + "properties": { + "forceDirect": { + "default": false, + "description": "If true, moving from one labware/well to another will not arc to the default safe z, but instead will move directly to the specified location. This will also force the `minimumZHeight` param to be ignored. A 'direct' movement is in X/Y/Z simultaneously.", + "title": "Forcedirect", + "type": "boolean" + }, + "labwareId": { + "description": "Identifier of labware to use.", + "title": "Labwareid", + "type": "string" + }, + "minimumZHeight": { + "description": "Optional minimal Z margin in mm. If this is larger than the API's default safe Z margin, it will make the arc higher. If it's smaller, it will have no effect.", + "title": "Minimumzheight", + "type": "number" + }, + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + }, + "speed": { + "description": "Override the travel speed in mm/s. This controls the straight linear speed of motion.", + "title": "Speed", + "type": "number" + }, + "wellLocation": { + "$ref": "#/$defs/WellLocation", + "description": "Relative well location at which to perform the operation" + }, + "wellName": { + "description": "Name of well to use in labware.", + "title": "Wellname", + "type": "string" + } + }, + "required": ["labwareId", "wellName", "pipetteId"], + "title": "MoveToWellParams", + "type": "object" + }, + "MovementAxis": { + "description": "Axis on which to issue a relative movement.", + "enum": ["x", "y", "z"], + "title": "MovementAxis", + "type": "string" + }, + "MultiDispenseProperties": { + "description": "Properties specific to the multi-dispense function.", + "properties": { + "conditioningByVolume": { + "description": "Settings for conditioning volume keyed by target dispense volume.", + "items": { + "maxItems": 2, + "minItems": 2, + "prefixItems": [ + { + "anyOf": [ + { + "minimum": 0, + "type": "integer" + }, + { + "minimum": 0.0, + "type": "number" + } + ] + }, + { + "anyOf": [ + { + "minimum": 0, + "type": "integer" + }, + { + "minimum": 0.0, + "type": "number" + } + ] + } + ], + "type": "array" + }, + "title": "Conditioningbyvolume", + "type": "array" + }, + "correctionByVolume": { + "description": "Settings for volume correction keyed by by target dispense volume, representing additional volume the plunger should move to accurately hit target volume.", + "items": { + "maxItems": 2, + "minItems": 2, + "prefixItems": [ + { + "anyOf": [ + { + "minimum": 0, + "type": "integer" + }, + { + "minimum": 0.0, + "type": "number" + } + ] + }, + { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "number" + } + ] + } + ], + "type": "array" + }, + "title": "Correctionbyvolume", + "type": "array" + }, + "delay": { + "$ref": "#/$defs/DelayProperties", + "description": "Delay settings after each dispense" + }, + "disposalByVolume": { + "description": "Settings for disposal volume keyed by target dispense volume.", + "items": { + "maxItems": 2, + "minItems": 2, + "prefixItems": [ + { + "anyOf": [ + { + "minimum": 0, + "type": "integer" + }, + { + "minimum": 0.0, + "type": "number" + } + ] + }, + { + "anyOf": [ + { + "minimum": 0, + "type": "integer" + }, + { + "minimum": 0.0, + "type": "number" + } + ] + } + ], + "type": "array" + }, + "title": "Disposalbyvolume", + "type": "array" + }, + "flowRateByVolume": { + "description": "Settings for flow rate keyed by target dispense volume.", + "items": { + "maxItems": 2, + "minItems": 2, + "prefixItems": [ + { + "anyOf": [ + { + "minimum": 0, + "type": "integer" + }, + { + "minimum": 0.0, + "type": "number" + } + ] + }, + { + "anyOf": [ + { + "minimum": 0, + "type": "integer" + }, + { + "minimum": 0.0, + "type": "number" + } + ] + } + ], + "type": "array" + }, + "title": "Flowratebyvolume", + "type": "array" + }, + "offset": { + "$ref": "#/$defs/Coordinate", + "description": "Relative offset for single multi-dispense." + }, + "positionReference": { + "$ref": "#/$defs/PositionReference", + "description": "Position reference for multi-dispense." + }, + "retract": { + "$ref": "#/$defs/RetractDispense", + "description": "Pipette retract settings after a multi-dispense." + }, + "submerge": { + "$ref": "#/$defs/Submerge", + "description": "Submerge settings for multi-dispense." + } + }, + "required": [ + "submerge", + "retract", + "positionReference", + "offset", + "flowRateByVolume", + "correctionByVolume", + "conditioningByVolume", + "disposalByVolume", + "delay" + ], + "title": "MultiDispenseProperties", + "type": "object" + }, + "OnLabwareLocation": { + "description": "The location of something placed atop another labware.", + "properties": { + "labwareId": { + "description": "The ID of a loaded Labware from a prior `loadLabware` command.", + "title": "Labwareid", + "type": "string" + } + }, + "required": ["labwareId"], + "title": "OnLabwareLocation", + "type": "object" + }, + "OpenLabwareLatchCreate": { + "description": "A request to create a Heater-Shaker's open labware latch command.", + "properties": { + "commandType": { + "const": "heaterShaker/openLabwareLatch", + "default": "heaterShaker/openLabwareLatch", + "enum": ["heaterShaker/openLabwareLatch"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/OpenLabwareLatchParams" + } + }, + "required": ["params"], + "title": "OpenLabwareLatchCreate", + "type": "object" + }, + "OpenLabwareLatchParams": { + "description": "Input parameters to open a Heater-Shaker Module's labware latch.", + "properties": { + "moduleId": { + "description": "Unique ID of the Heater-Shaker Module.", + "title": "Moduleid", + "type": "string" + } + }, + "required": ["moduleId"], + "title": "OpenLabwareLatchParams", + "type": "object" + }, + "PickUpTipCreate": { + "description": "Pick up tip command creation request model.", + "properties": { + "commandType": { + "const": "pickUpTip", + "default": "pickUpTip", + "enum": ["pickUpTip"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/PickUpTipParams" + } + }, + "required": ["params"], + "title": "PickUpTipCreate", + "type": "object" + }, + "PickUpTipParams": { + "description": "Payload needed to move a pipette to a specific well.", + "properties": { + "labwareId": { + "description": "Identifier of labware to use.", + "title": "Labwareid", + "type": "string" + }, + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + }, + "wellLocation": { + "$ref": "#/$defs/PickUpTipWellLocation", + "description": "Relative well location at which to pick up the tip." + }, + "wellName": { + "description": "Name of well to use in labware.", + "title": "Wellname", + "type": "string" + } + }, + "required": ["pipetteId", "labwareId", "wellName"], + "title": "PickUpTipParams", + "type": "object" + }, + "PickUpTipWellLocation": { + "description": "A relative location in reference to a well's location.\n\nTo be used for picking up tips.", + "properties": { + "offset": { + "$ref": "#/$defs/WellOffset" + }, + "origin": { + "$ref": "#/$defs/PickUpTipWellOrigin", + "default": "top" + } + }, + "title": "PickUpTipWellLocation", + "type": "object" + }, + "PickUpTipWellOrigin": { + "description": "The origin of a PickUpTipWellLocation offset.\n\nProps:\n TOP: the top-center of the well\n BOTTOM: the bottom-center of the well\n CENTER: the middle-center of the well", + "enum": ["top", "bottom", "center"], + "title": "PickUpTipWellOrigin", + "type": "string" + }, + "PipetteNameType": { + "description": "Pipette load name values.", + "enum": [ + "p10_single", + "p10_multi", + "p20_single_gen2", + "p20_multi_gen2", + "p50_single", + "p50_multi", + "p50_single_flex", + "p50_multi_flex", + "p300_single", + "p300_multi", + "p300_single_gen2", + "p300_multi_gen2", + "p1000_single", + "p1000_single_gen2", + "p1000_single_flex", + "p1000_multi_flex", + "p1000_multi_em_flex", + "p1000_96", + "p200_96" + ], + "title": "PipetteNameType", + "type": "string" + }, + "PositionReference": { + "description": "Positional reference for liquid handling operations.", + "enum": ["well-bottom", "well-top", "well-center", "liquid-meniscus"], + "title": "PositionReference", + "type": "string" + }, + "PrepareToAspirateCreate": { + "description": "Prepare for aspirate command creation request model.", + "properties": { + "commandType": { + "const": "prepareToAspirate", + "default": "prepareToAspirate", + "enum": ["prepareToAspirate"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/PrepareToAspirateParams" + } + }, + "required": ["params"], + "title": "PrepareToAspirateCreate", + "type": "object" + }, + "PrepareToAspirateParams": { + "description": "Parameters required to prepare a specific pipette for aspiration.", + "properties": { + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + } + }, + "required": ["pipetteId"], + "title": "PrepareToAspirateParams", + "type": "object" + }, + "ProfileCycle": { + "description": "An individual cycle in a Thermocycler extended profile.", + "properties": { + "repetitions": { + "description": "Number of times to repeat the steps.", + "title": "Repetitions", + "type": "integer" + }, + "steps": { + "description": "Steps to repeat.", + "items": { + "$ref": "#/$defs/ProfileStep" + }, + "title": "Steps", + "type": "array" + } + }, + "required": ["steps", "repetitions"], + "title": "ProfileCycle", + "type": "object" + }, + "ProfileStep": { + "description": "An individual step in a Thermocycler extended profile.", + "properties": { + "celsius": { + "description": "Target temperature in \u00b0C.", + "title": "Celsius", + "type": "number" + }, + "holdSeconds": { + "description": "Time to hold target temperature in seconds.", + "title": "Holdseconds", + "type": "number" + } + }, + "required": ["celsius", "holdSeconds"], + "title": "ProfileStep", + "type": "object" + }, + "QuadrantNozzleLayoutConfiguration": { + "description": "Information required for nozzle configurations of type QUADRANT.", + "properties": { + "backLeftNozzle": { + "description": "The back left nozzle in your configuration.", + "pattern": "[A-Z]\\d{1,2}", + "title": "Backleftnozzle", + "type": "string" + }, + "frontRightNozzle": { + "description": "The front right nozzle in your configuration.", + "pattern": "[A-Z]\\d{1,2}", + "title": "Frontrightnozzle", + "type": "string" + }, + "primaryNozzle": { + "description": "The primary nozzle to use in the layout configuration. This nozzle will update the critical point of the current pipette. For now, this is also the back left corner of your rectangle.", + "enum": ["A1", "H1", "A12", "H12"], + "title": "Primarynozzle", + "type": "string" + }, + "style": { + "const": "QUADRANT", + "default": "QUADRANT", + "enum": ["QUADRANT"], + "title": "Style", + "type": "string" + } + }, + "required": ["primaryNozzle", "frontRightNozzle", "backLeftNozzle"], + "title": "QuadrantNozzleLayoutConfiguration", + "type": "object" + }, + "ReadAbsorbanceCreate": { + "description": "A request to execute an Absorbance Reader measurement.", + "properties": { + "commandType": { + "const": "absorbanceReader/read", + "default": "absorbanceReader/read", + "enum": ["absorbanceReader/read"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/ReadAbsorbanceParams" + } + }, + "required": ["params"], + "title": "ReadAbsorbanceCreate", + "type": "object" + }, + "ReadAbsorbanceParams": { + "description": "Input parameters for an absorbance reading.", + "properties": { + "fileName": { + "description": "Optional file name to use when storing the results of a measurement.", + "title": "Filename", + "type": "string" + }, + "moduleId": { + "description": "Unique ID of the Absorbance Reader.", + "title": "Moduleid", + "type": "string" + } + }, + "required": ["moduleId"], + "title": "ReadAbsorbanceParams", + "type": "object" + }, + "ReloadLabwareCreate": { + "description": "Reload labware command creation request.", + "properties": { + "commandType": { + "const": "reloadLabware", + "default": "reloadLabware", + "enum": ["reloadLabware"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/ReloadLabwareParams" + } + }, + "required": ["params"], + "title": "ReloadLabwareCreate", + "type": "object" + }, + "ReloadLabwareParams": { + "description": "Payload required to load a labware into a slot.", + "properties": { + "labwareId": { + "description": "The already-loaded labware instance to update.", + "title": "Labwareid", + "type": "string" + } + }, + "required": ["labwareId"], + "title": "ReloadLabwareParams", + "type": "object" + }, + "RetractAspirate": { + "description": "Shared properties for the retract function after aspiration.", + "properties": { + "airGapByVolume": { + "description": "Settings for air gap keyed by target aspiration volume.", + "items": { + "maxItems": 2, + "minItems": 2, + "prefixItems": [ + { + "anyOf": [ + { + "minimum": 0, + "type": "integer" + }, + { + "minimum": 0.0, + "type": "number" + } + ] + }, + { + "anyOf": [ + { + "minimum": 0, + "type": "integer" + }, + { + "minimum": 0.0, + "type": "number" + } + ] + } + ], + "type": "array" + }, + "title": "Airgapbyvolume", + "type": "array" + }, + "delay": { + "$ref": "#/$defs/DelayProperties", + "description": "Delay settings for retract after aspirate." + }, + "offset": { + "$ref": "#/$defs/Coordinate", + "description": "Relative offset for retract after aspirate." + }, + "positionReference": { + "$ref": "#/$defs/PositionReference", + "description": "Position reference for retract after aspirate." + }, + "speed": { + "anyOf": [ + { + "minimum": 0, + "type": "integer" + }, + { + "minimum": 0.0, + "type": "number" + } + ], + "description": "Speed of retraction, in millimeters per second.", + "title": "Speed" + }, + "touchTip": { + "$ref": "#/$defs/TouchTipProperties", + "description": "Touch tip settings for retract after aspirate." + } + }, + "required": [ + "positionReference", + "offset", + "speed", + "airGapByVolume", + "touchTip", + "delay" + ], + "title": "RetractAspirate", + "type": "object" + }, + "RetractAxisCreate": { + "description": "Data to create a Retract Axis command.", + "properties": { + "commandType": { + "const": "retractAxis", + "default": "retractAxis", + "enum": ["retractAxis"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/RetractAxisParams" + } + }, + "required": ["params"], + "title": "RetractAxisCreate", + "type": "object" + }, + "RetractAxisParams": { + "description": "Payload required for a Retract Axis command.", + "properties": { + "axis": { + "$ref": "#/$defs/MotorAxis", + "description": "Axis to retract to its home position as quickly as safely possible. The difference between retracting an axis and homing an axis using the home command is that a home will always probe the limit switch and will work as the first motion command a robot will need to execute; On the other hand, retraction will rely on this previously determined home position to move to it as fast as safely possible. So on the Flex, it will move (fast) the axis to the previously recorded home position and on the OT2, it will move (fast) the axis a safe distance from the previously recorded home position, and then slowly approach the limit switch." + } + }, + "required": ["axis"], + "title": "RetractAxisParams", + "type": "object" + }, + "RetractDispense": { + "description": "Shared properties for the retract function after dispense.", + "properties": { + "airGapByVolume": { + "description": "Settings for air gap keyed by target aspiration volume.", + "items": { + "maxItems": 2, + "minItems": 2, + "prefixItems": [ + { + "anyOf": [ + { + "minimum": 0, + "type": "integer" + }, + { + "minimum": 0.0, + "type": "number" + } + ] + }, + { + "anyOf": [ + { + "minimum": 0, + "type": "integer" + }, + { + "minimum": 0.0, + "type": "number" + } + ] + } + ], + "type": "array" + }, + "title": "Airgapbyvolume", + "type": "array" + }, + "blowout": { + "$ref": "#/$defs/BlowoutProperties", + "description": "Blowout properties for retract after dispense." + }, + "delay": { + "$ref": "#/$defs/DelayProperties", + "description": "Delay settings for retract after dispense." + }, + "offset": { + "$ref": "#/$defs/Coordinate", + "description": "Relative offset for retract after dispense." + }, + "positionReference": { + "$ref": "#/$defs/PositionReference", + "description": "Position reference for retract after dispense." + }, + "speed": { + "anyOf": [ + { + "minimum": 0, + "type": "integer" + }, + { + "minimum": 0.0, + "type": "number" + } + ], + "description": "Speed of retraction, in millimeters per second.", + "title": "Speed" + }, + "touchTip": { + "$ref": "#/$defs/TouchTipProperties", + "description": "Touch tip settings for retract after dispense." + } + }, + "required": [ + "positionReference", + "offset", + "speed", + "airGapByVolume", + "blowout", + "touchTip", + "delay" + ], + "title": "RetractDispense", + "type": "object" + }, + "RetrieveCreate": { + "description": "A request to execute a Flex Stacker retrieve command.", + "properties": { + "commandType": { + "const": "flexStacker/retrieve", + "default": "flexStacker/retrieve", + "enum": ["flexStacker/retrieve"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/RetrieveParams" + } + }, + "required": ["params"], + "title": "RetrieveCreate", + "type": "object" + }, + "RetrieveParams": { + "description": "Input parameters for a labware retrieval command.", + "properties": { + "moduleId": { + "description": "Unique ID of the Flex Stacker.", + "title": "Moduleid", + "type": "string" + } + }, + "required": ["moduleId"], + "title": "RetrieveParams", + "type": "object" + }, + "RowNozzleLayoutConfiguration": { + "description": "Minimum information required for a new nozzle configuration.", + "properties": { + "primaryNozzle": { + "description": "The primary nozzle to use in the layout configuration. This nozzle will update the critical point of the current pipette. For now, this is also the back left corner of your rectangle.", + "enum": ["A1", "H1", "A12", "H12"], + "title": "Primarynozzle", + "type": "string" + }, + "style": { + "const": "ROW", + "default": "ROW", + "enum": ["ROW"], + "title": "Style", + "type": "string" + } + }, + "required": ["primaryNozzle"], + "title": "RowNozzleLayoutConfiguration", + "type": "object" + }, + "RunExtendedProfileCreate": { + "description": "A request to execute a Thermocycler profile run.", + "properties": { + "commandType": { + "const": "thermocycler/runExtendedProfile", + "default": "thermocycler/runExtendedProfile", + "enum": ["thermocycler/runExtendedProfile"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/RunExtendedProfileParams" + } + }, + "required": ["params"], + "title": "RunExtendedProfileCreate", + "type": "object" + }, + "RunExtendedProfileParams": { + "description": "Input parameters for an individual Thermocycler profile step.", + "properties": { + "blockMaxVolumeUl": { + "description": "Amount of liquid in uL of the most-full well in labware loaded onto the thermocycler.", + "title": "Blockmaxvolumeul", + "type": "number" + }, + "moduleId": { + "description": "Unique ID of the Thermocycler.", + "title": "Moduleid", + "type": "string" + }, + "profileElements": { + "description": "Elements of the profile. Each can be either a step or a cycle.", + "items": { + "anyOf": [ + { + "$ref": "#/$defs/ProfileStep" + }, + { + "$ref": "#/$defs/ProfileCycle" + } + ] + }, + "title": "Profileelements", + "type": "array" + } + }, + "required": ["moduleId", "profileElements"], + "title": "RunExtendedProfileParams", + "type": "object" + }, + "RunProfileCreate": { + "description": "A request to execute a Thermocycler profile run.", + "properties": { + "commandType": { + "const": "thermocycler/runProfile", + "default": "thermocycler/runProfile", + "enum": ["thermocycler/runProfile"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/RunProfileParams" + } + }, + "required": ["params"], + "title": "RunProfileCreate", + "type": "object" + }, + "RunProfileParams": { + "description": "Input parameters to run a Thermocycler profile.", + "properties": { + "blockMaxVolumeUl": { + "description": "Amount of liquid in uL of the most-full well in labware loaded onto the thermocycler.", + "title": "Blockmaxvolumeul", + "type": "number" + }, + "moduleId": { + "description": "Unique ID of the Thermocycler.", + "title": "Moduleid", + "type": "string" + }, + "profile": { + "description": "Array of profile steps with target temperature and temperature hold time.", + "items": { + "$ref": "#/$defs/RunProfileStepParams" + }, + "title": "Profile", + "type": "array" + } + }, + "required": ["moduleId", "profile"], + "title": "RunProfileParams", + "type": "object" + }, + "RunProfileStepParams": { + "description": "Input parameters for an individual Thermocycler profile step.", + "properties": { + "celsius": { + "description": "Target temperature in \u00b0C.", + "title": "Celsius", + "type": "number" + }, + "holdSeconds": { + "description": "Time to hold target temperature at in seconds.", + "title": "Holdseconds", + "type": "number" + } + }, + "required": ["celsius", "holdSeconds"], + "title": "RunProfileStepParams", + "type": "object" + }, + "SavePositionCreate": { + "description": "Save position command creation request model.", + "properties": { + "commandType": { + "const": "savePosition", + "default": "savePosition", + "enum": ["savePosition"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/SavePositionParams" + } + }, + "required": ["params"], + "title": "SavePositionCreate", + "type": "object" + }, + "SavePositionParams": { + "description": "Payload needed to save a pipette's current position.", + "properties": { + "failOnNotHomed": { + "description": "Require all axes to be homed before saving position.", + "title": "Failonnothomed", + "type": "boolean" + }, + "pipetteId": { + "description": "Unique identifier of the pipette in question.", + "title": "Pipetteid", + "type": "string" + }, + "positionId": { + "description": "An optional ID to assign to this command instance. Auto-assigned if not defined.", + "title": "Positionid", + "type": "string" + } + }, + "required": ["pipetteId"], + "title": "SavePositionParams", + "type": "object" + }, + "SetAndWaitForShakeSpeedCreate": { + "description": "A request to create a Heater-Shaker's set and wait for shake speed command.", + "properties": { + "commandType": { + "const": "heaterShaker/setAndWaitForShakeSpeed", + "default": "heaterShaker/setAndWaitForShakeSpeed", + "enum": ["heaterShaker/setAndWaitForShakeSpeed"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/SetAndWaitForShakeSpeedParams" + } + }, + "required": ["params"], + "title": "SetAndWaitForShakeSpeedCreate", + "type": "object" + }, + "SetAndWaitForShakeSpeedParams": { + "description": "Input parameters to set and wait for a shake speed for a Heater-Shaker Module.", + "properties": { + "moduleId": { + "description": "Unique ID of the Heater-Shaker Module.", + "title": "Moduleid", + "type": "string" + }, + "rpm": { + "description": "Target speed in rotations per minute.", + "title": "Rpm", + "type": "number" + } + }, + "required": ["moduleId", "rpm"], + "title": "SetAndWaitForShakeSpeedParams", + "type": "object" + }, + "SetRailLightsCreate": { + "description": "setRailLights command request model.", + "properties": { + "commandType": { + "const": "setRailLights", + "default": "setRailLights", + "enum": ["setRailLights"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/SetRailLightsParams" + } + }, + "required": ["params"], + "title": "SetRailLightsCreate", + "type": "object" + }, + "SetRailLightsParams": { + "description": "Payload required to set the rail lights on or off.", + "properties": { + "on": { + "description": "The field that determines if the light is turned off or on.", + "title": "On", + "type": "boolean" + } + }, + "required": ["on"], + "title": "SetRailLightsParams", + "type": "object" + }, + "SetStatusBarCreate": { + "description": "setStatusBar command request model.", + "properties": { + "commandType": { + "const": "setStatusBar", + "default": "setStatusBar", + "enum": ["setStatusBar"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/SetStatusBarParams" + } + }, + "required": ["params"], + "title": "SetStatusBarCreate", + "type": "object" + }, + "SetStatusBarParams": { + "description": "Payload required to set the status bar to run an animation.", + "properties": { + "animation": { + "$ref": "#/$defs/StatusBarAnimation", + "description": "The animation that should be executed on the status bar." + } + }, + "required": ["animation"], + "title": "SetStatusBarParams", + "type": "object" + }, + "SetTargetBlockTemperatureCreate": { + "description": "A request to create a Thermocycler's set block temperature command.", + "properties": { + "commandType": { + "const": "thermocycler/setTargetBlockTemperature", + "default": "thermocycler/setTargetBlockTemperature", + "enum": ["thermocycler/setTargetBlockTemperature"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/SetTargetBlockTemperatureParams" + } + }, + "required": ["params"], + "title": "SetTargetBlockTemperatureCreate", + "type": "object" + }, + "SetTargetBlockTemperatureParams": { + "description": "Input parameters to set a Thermocycler's target block temperature.", + "properties": { + "blockMaxVolumeUl": { + "description": "Amount of liquid in uL of the most-full well in labware loaded onto the thermocycler.", + "title": "Blockmaxvolumeul", + "type": "number" + }, + "celsius": { + "description": "Target temperature in \u00b0C.", + "title": "Celsius", + "type": "number" + }, + "holdTimeSeconds": { + "description": "Amount of time, in seconds, to hold the temperature for. If specified, a waitForBlockTemperature command will block until the given hold time has elapsed.", + "title": "Holdtimeseconds", + "type": "number" + }, + "moduleId": { + "description": "Unique ID of the Thermocycler Module.", + "title": "Moduleid", + "type": "string" + } + }, + "required": ["moduleId", "celsius"], + "title": "SetTargetBlockTemperatureParams", + "type": "object" + }, + "SetTargetLidTemperatureCreate": { + "description": "A request to create a Thermocycler's set lid temperature command.", + "properties": { + "commandType": { + "const": "thermocycler/setTargetLidTemperature", + "default": "thermocycler/setTargetLidTemperature", + "enum": ["thermocycler/setTargetLidTemperature"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/SetTargetLidTemperatureParams" + } + }, + "required": ["params"], + "title": "SetTargetLidTemperatureCreate", + "type": "object" + }, + "SetTargetLidTemperatureParams": { + "description": "Input parameters to set a Thermocycler's target lid temperature.", + "properties": { + "celsius": { + "description": "Target temperature in \u00b0C.", + "title": "Celsius", + "type": "number" + }, + "moduleId": { + "description": "Unique ID of the Thermocycler Module.", + "title": "Moduleid", + "type": "string" + } + }, + "required": ["moduleId", "celsius"], + "title": "SetTargetLidTemperatureParams", + "type": "object" + }, + "SingleDispenseProperties": { + "description": "Properties specific to the single-dispense function.", + "properties": { + "correctionByVolume": { + "description": "Settings for volume correction keyed by by target dispense volume, representing additional volume the plunger should move to accurately hit target volume.", + "items": { + "maxItems": 2, + "minItems": 2, + "prefixItems": [ + { + "anyOf": [ + { + "minimum": 0, + "type": "integer" + }, + { + "minimum": 0.0, + "type": "number" + } + ] + }, + { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "number" + } + ] + } + ], + "type": "array" + }, + "title": "Correctionbyvolume", + "type": "array" + }, + "delay": { + "$ref": "#/$defs/DelayProperties", + "description": "Delay after dispense, in seconds." + }, + "flowRateByVolume": { + "description": "Settings for flow rate keyed by target dispense volume.", + "items": { + "maxItems": 2, + "minItems": 2, + "prefixItems": [ + { + "anyOf": [ + { + "minimum": 0, + "type": "integer" + }, + { + "minimum": 0.0, + "type": "number" + } + ] + }, + { + "anyOf": [ + { + "minimum": 0, + "type": "integer" + }, + { + "minimum": 0.0, + "type": "number" + } + ] + } + ], + "type": "array" + }, + "title": "Flowratebyvolume", + "type": "array" + }, + "mix": { + "$ref": "#/$defs/MixProperties", + "description": "Mixing settings for after a dispense" + }, + "offset": { + "$ref": "#/$defs/Coordinate", + "description": "Relative offset for single dispense." + }, + "positionReference": { + "$ref": "#/$defs/PositionReference", + "description": "Position reference for single dispense." + }, + "pushOutByVolume": { + "description": "Settings for pushout keyed by target dispense volume.", + "items": { + "maxItems": 2, + "minItems": 2, + "prefixItems": [ + { + "anyOf": [ + { + "minimum": 0, + "type": "integer" + }, + { + "minimum": 0.0, + "type": "number" + } + ] + }, + { + "anyOf": [ + { + "minimum": 0, + "type": "integer" + }, + { + "minimum": 0.0, + "type": "number" + } + ] + } + ], + "type": "array" + }, + "title": "Pushoutbyvolume", + "type": "array" + }, + "retract": { + "$ref": "#/$defs/RetractDispense", + "description": "Pipette retract settings after a single dispense." + }, + "submerge": { + "$ref": "#/$defs/Submerge", + "description": "Submerge settings for single dispense." + } + }, + "required": [ + "submerge", + "retract", + "positionReference", + "offset", + "flowRateByVolume", + "correctionByVolume", + "mix", + "pushOutByVolume", + "delay" + ], + "title": "SingleDispenseProperties", + "type": "object" + }, + "SingleNozzleLayoutConfiguration": { + "description": "Minimum information required for a new nozzle configuration.", + "properties": { + "primaryNozzle": { + "description": "The primary nozzle to use in the layout configuration. This nozzle will update the critical point of the current pipette. For now, this is also the back left corner of your rectangle.", + "enum": ["A1", "H1", "A12", "H12"], + "title": "Primarynozzle", + "type": "string" + }, + "style": { + "const": "SINGLE", + "default": "SINGLE", + "enum": ["SINGLE"], + "title": "Style", + "type": "string" + } + }, + "required": ["primaryNozzle"], + "title": "SingleNozzleLayoutConfiguration", + "type": "object" + }, + "StatusBarAnimation": { + "description": "Status Bar animation options.", + "enum": ["idle", "confirm", "updating", "disco", "off"], + "title": "StatusBarAnimation", + "type": "string" + }, + "StoreCreate": { + "description": "A request to execute a Flex Stacker store command.", + "properties": { + "commandType": { + "const": "flexStacker/store", + "default": "flexStacker/store", + "enum": ["flexStacker/store"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/StoreParams" + } + }, + "required": ["params"], + "title": "StoreCreate", + "type": "object" + }, + "StoreParams": { + "description": "Input parameters for a labware storage command.", + "properties": { + "moduleId": { + "description": "Unique ID of the flex stacker.", + "title": "Moduleid", + "type": "string" + } + }, + "required": ["moduleId"], + "title": "StoreParams", + "type": "object" + }, + "Submerge": { + "description": "Shared properties for the submerge function before aspiration or dispense.", + "properties": { + "delay": { + "$ref": "#/$defs/DelayProperties", + "description": "Delay settings for submerge." + }, + "offset": { + "$ref": "#/$defs/Coordinate", + "description": "Relative offset for submerge." + }, + "positionReference": { + "$ref": "#/$defs/PositionReference", + "description": "Position reference for submerge." + }, + "speed": { + "anyOf": [ + { + "minimum": 0, + "type": "integer" + }, + { + "minimum": 0.0, + "type": "number" + } + ], + "description": "Speed of submerging, in millimeters per second.", + "title": "Speed" + } + }, + "required": ["positionReference", "offset", "speed", "delay"], + "title": "Submerge", + "type": "object" + }, + "TipPresenceStatus": { + "description": "Tip presence status reported by a pipette.", + "enum": ["present", "absent", "unknown"], + "title": "TipPresenceStatus", + "type": "string" + }, + "TouchTipCreate": { + "description": "Touch tip command creation request model.", + "properties": { + "commandType": { + "const": "touchTip", + "default": "touchTip", + "enum": ["touchTip"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/TouchTipParams" + } + }, + "required": ["params"], + "title": "TouchTipCreate", + "type": "object" + }, + "TouchTipParams": { + "description": "Payload needed to touch a pipette tip the sides of a specific well.", + "properties": { + "labwareId": { + "description": "Identifier of labware to use.", + "title": "Labwareid", + "type": "string" + }, + "mmFromEdge": { + "description": "Offset away from the the well edge, in millimeters.Incompatible when a radius is included as a non 1.0 value.", + "title": "Mmfromedge", + "type": "number" + }, + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + }, + "radius": { + "default": 1.0, + "description": "The proportion of the target well's radius the pipette tip will move towards.", + "title": "Radius", + "type": "number" + }, + "speed": { + "description": "Override the travel speed in mm/s. This controls the straight linear speed of motion.", + "title": "Speed", + "type": "number" + }, + "wellLocation": { + "$ref": "#/$defs/WellLocation", + "description": "Relative well location at which to perform the operation" + }, + "wellName": { + "description": "Name of well to use in labware.", + "title": "Wellname", + "type": "string" + } + }, + "required": ["labwareId", "wellName", "pipetteId"], + "title": "TouchTipParams", + "type": "object" + }, + "TouchTipProperties": { + "description": "Shared properties for the touch-tip function.", + "properties": { + "enable": { + "description": "Whether touch-tip is enabled.", + "title": "Enable", + "type": "boolean" + }, + "params": { + "$ref": "#/$defs/LiquidClassTouchTipParams", + "description": "Parameters for the touch-tip function.", + "title": "Params" + } + }, + "required": ["enable"], + "title": "TouchTipProperties", + "type": "object" + }, + "TryLiquidProbeCreate": { + "description": "The request model for a `tryLiquidProbe` command.", + "properties": { + "commandType": { + "const": "tryLiquidProbe", + "default": "tryLiquidProbe", + "enum": ["tryLiquidProbe"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/TryLiquidProbeParams" + } + }, + "required": ["params"], + "title": "TryLiquidProbeCreate", + "type": "object" + }, + "TryLiquidProbeParams": { + "description": "Parameters required for a `tryLiquidProbe` command.", + "properties": { + "labwareId": { + "description": "Identifier of labware to use.", + "title": "Labwareid", + "type": "string" + }, + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + }, + "wellLocation": { + "$ref": "#/$defs/WellLocation", + "description": "Relative well location at which to perform the operation" + }, + "wellName": { + "description": "Name of well to use in labware.", + "title": "Wellname", + "type": "string" + } + }, + "required": ["labwareId", "wellName", "pipetteId"], + "title": "TryLiquidProbeParams", + "type": "object" + }, + "UnsafeBlowOutInPlaceCreate": { + "description": "UnsafeBlowOutInPlace command request model.", + "properties": { + "commandType": { + "const": "unsafe/blowOutInPlace", + "default": "unsafe/blowOutInPlace", + "enum": ["unsafe/blowOutInPlace"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/UnsafeBlowOutInPlaceParams" + } + }, + "required": ["params"], + "title": "UnsafeBlowOutInPlaceCreate", + "type": "object" + }, + "UnsafeBlowOutInPlaceParams": { + "description": "Payload required to blow-out in place while position is unknown.", + "properties": { + "flowRate": { + "description": "Speed in \u00b5L/s configured for the pipette", + "exclusiveMinimum": 0.0, + "title": "Flowrate", + "type": "number" + }, + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + } + }, + "required": ["flowRate", "pipetteId"], + "title": "UnsafeBlowOutInPlaceParams", + "type": "object" + }, + "UnsafeDropTipInPlaceCreate": { + "description": "Drop tip in place command creation request model.", + "properties": { + "commandType": { + "const": "unsafe/dropTipInPlace", + "default": "unsafe/dropTipInPlace", + "enum": ["unsafe/dropTipInPlace"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/UnsafeDropTipInPlaceParams" + } + }, + "required": ["params"], + "title": "UnsafeDropTipInPlaceCreate", + "type": "object" + }, + "UnsafeDropTipInPlaceParams": { + "description": "Payload required to drop a tip in place even if the plunger position is not known.", + "properties": { + "homeAfter": { + "description": "Whether to home this pipette's plunger after dropping the tip. You should normally leave this unspecified to let the robot choose a safe default depending on its hardware.", + "title": "Homeafter", + "type": "boolean" + }, + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + } + }, + "required": ["pipetteId"], + "title": "UnsafeDropTipInPlaceParams", + "type": "object" + }, + "UnsafeEngageAxesCreate": { + "description": "UnsafeEngageAxes command request model.", + "properties": { + "commandType": { + "const": "unsafe/engageAxes", + "default": "unsafe/engageAxes", + "enum": ["unsafe/engageAxes"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/UnsafeEngageAxesParams" + } + }, + "required": ["params"], + "title": "UnsafeEngageAxesCreate", + "type": "object" + }, + "UnsafeEngageAxesParams": { + "description": "Payload required for an UnsafeEngageAxes command.", + "properties": { + "axes": { + "description": "The axes for which to enable.", + "items": { + "$ref": "#/$defs/MotorAxis" + }, + "title": "Axes", + "type": "array" + } + }, + "required": ["axes"], + "title": "UnsafeEngageAxesParams", + "type": "object" + }, + "UnsafePlaceLabwareCreate": { + "description": "UnsafePlaceLabware command request model.", + "properties": { + "commandType": { + "const": "unsafe/placeLabware", + "default": "unsafe/placeLabware", + "enum": ["unsafe/placeLabware"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/UnsafePlaceLabwareParams" + } + }, + "required": ["params"], + "title": "UnsafePlaceLabwareCreate", + "type": "object" + }, + "UnsafePlaceLabwareParams": { + "description": "Payload required for an UnsafePlaceLabware command.", + "properties": { + "labwareURI": { + "description": "Labware URI for labware.", + "title": "Labwareuri", + "type": "string" + }, + "location": { + "anyOf": [ + { + "$ref": "#/$defs/DeckSlotLocation" + }, + { + "$ref": "#/$defs/ModuleLocation" + }, + { + "$ref": "#/$defs/OnLabwareLocation" + }, + { + "$ref": "#/$defs/AddressableAreaLocation" + } + ], + "description": "Where to place the labware.", + "title": "Location" + } + }, + "required": ["labwareURI", "location"], + "title": "UnsafePlaceLabwareParams", + "type": "object" + }, + "UnsafeUngripLabwareCreate": { + "description": "UnsafeEngageAxes command request model.", + "properties": { + "commandType": { + "const": "unsafe/ungripLabware", + "default": "unsafe/ungripLabware", + "enum": ["unsafe/ungripLabware"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/UnsafeUngripLabwareParams" + } + }, + "required": ["params"], + "title": "UnsafeUngripLabwareCreate", + "type": "object" + }, + "UnsafeUngripLabwareParams": { + "description": "Payload required for an UngripLabware command.", + "properties": {}, + "title": "UnsafeUngripLabwareParams", + "type": "object" + }, + "UpdatePositionEstimatorsCreate": { + "description": "UpdatePositionEstimators command request model.", + "properties": { + "commandType": { + "const": "unsafe/updatePositionEstimators", + "default": "unsafe/updatePositionEstimators", + "enum": ["unsafe/updatePositionEstimators"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/UpdatePositionEstimatorsParams" + } + }, + "required": ["params"], + "title": "UpdatePositionEstimatorsCreate", + "type": "object" + }, + "UpdatePositionEstimatorsParams": { + "description": "Payload required for an UpdatePositionEstimators command.", + "properties": { + "axes": { + "description": "The axes for which to update the position estimators. Any axes that are not physically present will be ignored.", + "items": { + "$ref": "#/$defs/MotorAxis" + }, + "title": "Axes", + "type": "array" + } + }, + "required": ["axes"], + "title": "UpdatePositionEstimatorsParams", + "type": "object" + }, + "Vec3f": { + "description": "A 3D vector of floats.", + "properties": { + "x": { + "title": "X", + "type": "number" + }, + "y": { + "title": "Y", + "type": "number" + }, + "z": { + "title": "Z", + "type": "number" + } + }, + "required": ["x", "y", "z"], + "title": "Vec3f", + "type": "object" + }, + "VerifyTipPresenceCreate": { + "description": "VerifyTipPresence command creation request model.", + "properties": { + "commandType": { + "const": "verifyTipPresence", + "default": "verifyTipPresence", + "enum": ["verifyTipPresence"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/VerifyTipPresenceParams" + } + }, + "required": ["params"], + "title": "VerifyTipPresenceCreate", + "type": "object" + }, + "VerifyTipPresenceParams": { + "description": "Payload required for a VerifyTipPresence command.", + "properties": { + "expectedState": { + "$ref": "#/$defs/TipPresenceStatus", + "description": "The expected tip presence status on the pipette." + }, + "followSingularSensor": { + "$ref": "#/$defs/InstrumentSensorId", + "description": "The sensor id to follow if the other can be ignored.", + "title": "Followsingularsensor" + }, + "pipetteId": { + "description": "Identifier of pipette to use for liquid handling.", + "title": "Pipetteid", + "type": "string" + } + }, + "required": ["pipetteId", "expectedState"], + "title": "VerifyTipPresenceParams", + "type": "object" + }, + "WaitForBlockTemperatureCreate": { + "description": "A request to create Thermocycler's wait for block temperature command.", + "properties": { + "commandType": { + "const": "thermocycler/waitForBlockTemperature", + "default": "thermocycler/waitForBlockTemperature", + "enum": ["thermocycler/waitForBlockTemperature"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/WaitForBlockTemperatureParams" + } + }, + "required": ["params"], + "title": "WaitForBlockTemperatureCreate", + "type": "object" + }, + "WaitForBlockTemperatureParams": { + "description": "Input parameters to wait for Thermocycler's target block temperature.", + "properties": { + "moduleId": { + "description": "Unique ID of the Thermocycler Module.", + "title": "Moduleid", + "type": "string" + } + }, + "required": ["moduleId"], + "title": "WaitForBlockTemperatureParams", + "type": "object" + }, + "WaitForDurationCreate": { + "description": "Wait for duration command request model.", + "properties": { + "commandType": { + "const": "waitForDuration", + "default": "waitForDuration", + "enum": ["waitForDuration"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/WaitForDurationParams" + } + }, + "required": ["params"], + "title": "WaitForDurationCreate", + "type": "object" + }, + "WaitForDurationParams": { + "description": "Payload required to pause the protocol.", + "properties": { + "message": { + "description": "A user-facing message associated with the pause", + "title": "Message", + "type": "string" + }, + "seconds": { + "description": "Duration, in seconds, to wait for.", + "title": "Seconds", + "type": "number" + } + }, + "required": ["seconds"], + "title": "WaitForDurationParams", + "type": "object" + }, + "WaitForLidTemperatureCreate": { + "description": "A request to create Thermocycler's wait for lid temperature command.", + "properties": { + "commandType": { + "const": "thermocycler/waitForLidTemperature", + "default": "thermocycler/waitForLidTemperature", + "enum": ["thermocycler/waitForLidTemperature"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/WaitForLidTemperatureParams" + } + }, + "required": ["params"], + "title": "WaitForLidTemperatureCreate", + "type": "object" + }, + "WaitForLidTemperatureParams": { + "description": "Input parameters to wait for Thermocycler's lid temperature.", + "properties": { + "moduleId": { + "description": "Unique ID of the Thermocycler Module.", + "title": "Moduleid", + "type": "string" + } + }, + "required": ["moduleId"], + "title": "WaitForLidTemperatureParams", + "type": "object" + }, + "WaitForResumeCreate": { + "description": "Wait for resume command request model.", + "properties": { + "commandType": { + "default": "waitForResume", + "enum": ["waitForResume", "pause"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/WaitForResumeParams" + } + }, + "required": ["params"], + "title": "WaitForResumeCreate", + "type": "object" + }, + "WaitForResumeParams": { + "description": "Payload required to pause the protocol.", + "properties": { + "message": { + "description": "A user-facing message associated with the pause", + "title": "Message", + "type": "string" + } + }, + "title": "WaitForResumeParams", + "type": "object" + }, + "WellLocation": { + "description": "A relative location in reference to a well's location.", + "properties": { + "offset": { + "$ref": "#/$defs/WellOffset" + }, + "origin": { + "$ref": "#/$defs/WellOrigin", + "default": "top" + }, + "volumeOffset": { + "default": 0.0, + "description": "A volume of liquid, in \u00b5L, to offset the z-axis offset.", + "title": "Volumeoffset", + "type": "number" + } + }, + "title": "WellLocation", + "type": "object" + }, + "WellOffset": { + "description": "An offset vector in (x, y, z).", + "properties": { + "x": { + "default": 0, + "title": "X", + "type": "number" + }, + "y": { + "default": 0, + "title": "Y", + "type": "number" + }, + "z": { + "default": 0, + "title": "Z", + "type": "number" + } + }, + "title": "WellOffset", + "type": "object" + }, + "WellOrigin": { + "description": "Origin of WellLocation offset.\n\nProps:\n TOP: the top-center of the well\n BOTTOM: the bottom-center of the well\n CENTER: the middle-center of the well\n MENISCUS: the meniscus-center of the well", + "enum": ["top", "bottom", "center", "meniscus"], + "title": "WellOrigin", + "type": "string" + }, + "closeGripperJawCreate": { + "description": "closeGripperJaw command request model.", + "properties": { + "commandType": { + "const": "robot/closeGripperJaw", + "default": "robot/closeGripperJaw", + "enum": ["robot/closeGripperJaw"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/closeGripperJawParams" + } + }, + "required": ["params"], + "title": "closeGripperJawCreate", + "type": "object" + }, + "closeGripperJawParams": { + "description": "Payload required to close a gripper.", + "properties": { + "force": { + "description": "The force the gripper should use to hold the jaws, falls to default if none is provided.", + "title": "Force", + "type": "number" + } + }, + "title": "closeGripperJawParams", + "type": "object" + }, + "openGripperJawCreate": { + "description": "openGripperJaw command request model.", + "properties": { + "commandType": { + "const": "robot/openGripperJaw", + "default": "robot/openGripperJaw", + "enum": ["robot/openGripperJaw"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/openGripperJawParams" + } + }, + "required": ["params"], + "title": "openGripperJawCreate", + "type": "object" + }, + "openGripperJawParams": { + "description": "Payload required to release a gripper.", + "properties": {}, + "title": "openGripperJawParams", + "type": "object" + }, + "opentrons__protocol_engine__commands__absorbance_reader__close_lid__CloseLidCreate": { + "description": "A request to execute an Absorbance Reader close lid command.", + "properties": { + "commandType": { + "const": "absorbanceReader/closeLid", + "default": "absorbanceReader/closeLid", + "enum": ["absorbanceReader/closeLid"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/opentrons__protocol_engine__commands__absorbance_reader__close_lid__CloseLidParams" + } + }, + "required": ["params"], + "title": "CloseLidCreate", + "type": "object" + }, + "opentrons__protocol_engine__commands__absorbance_reader__close_lid__CloseLidParams": { + "description": "Input parameters to close the lid on an absorbance reading.", + "properties": { + "moduleId": { + "description": "Unique ID of the absorbance reader.", + "title": "Moduleid", + "type": "string" + } + }, + "required": ["moduleId"], + "title": "CloseLidParams", + "type": "object" + }, + "opentrons__protocol_engine__commands__absorbance_reader__open_lid__OpenLidCreate": { + "description": "A request to execute an Absorbance Reader open lid command.", + "properties": { + "commandType": { + "const": "absorbanceReader/openLid", + "default": "absorbanceReader/openLid", + "enum": ["absorbanceReader/openLid"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/opentrons__protocol_engine__commands__absorbance_reader__open_lid__OpenLidParams" + } + }, + "required": ["params"], + "title": "OpenLidCreate", + "type": "object" + }, + "opentrons__protocol_engine__commands__absorbance_reader__open_lid__OpenLidParams": { + "description": "Input parameters to open the lid on an absorbance reading.", + "properties": { + "moduleId": { + "description": "Unique ID of the absorbance reader.", + "title": "Moduleid", + "type": "string" + } + }, + "required": ["moduleId"], + "title": "OpenLidParams", + "type": "object" + }, + "opentrons__protocol_engine__commands__heater_shaker__set_target_temperature__SetTargetTemperatureCreate": { + "description": "A request to create a Heater-Shaker's set temperature command.", + "properties": { + "commandType": { + "const": "heaterShaker/setTargetTemperature", + "default": "heaterShaker/setTargetTemperature", + "enum": ["heaterShaker/setTargetTemperature"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/opentrons__protocol_engine__commands__heater_shaker__set_target_temperature__SetTargetTemperatureParams" + } + }, + "required": ["params"], + "title": "SetTargetTemperatureCreate", + "type": "object" + }, + "opentrons__protocol_engine__commands__heater_shaker__set_target_temperature__SetTargetTemperatureParams": { + "description": "Input parameters to set a Heater-Shaker's target temperature.", + "properties": { + "celsius": { + "description": "Target temperature in \u00b0C.", + "title": "Celsius", + "type": "number" + }, + "moduleId": { + "description": "Unique ID of the Heater-Shaker Module.", + "title": "Moduleid", + "type": "string" + } + }, + "required": ["moduleId", "celsius"], + "title": "SetTargetTemperatureParams", + "type": "object" + }, + "opentrons__protocol_engine__commands__heater_shaker__wait_for_temperature__WaitForTemperatureCreate": { + "description": "A request to create a Heater-Shaker's wait for temperature command.", + "properties": { + "commandType": { + "const": "heaterShaker/waitForTemperature", + "default": "heaterShaker/waitForTemperature", + "enum": ["heaterShaker/waitForTemperature"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/opentrons__protocol_engine__commands__heater_shaker__wait_for_temperature__WaitForTemperatureParams" + } + }, + "required": ["params"], + "title": "WaitForTemperatureCreate", + "type": "object" + }, + "opentrons__protocol_engine__commands__heater_shaker__wait_for_temperature__WaitForTemperatureParams": { + "description": "Input parameters to wait for a Heater-Shaker's target temperature.", + "properties": { + "celsius": { + "description": "Target temperature in \u00b0C. If not specified, will default to the module's target temperature. Specifying a celsius parameter other than the target temperature could lead to unpredictable behavior and hence is not recommended for use. This parameter can be removed in a future version without prior notice.", + "title": "Celsius", + "type": "number" + }, + "moduleId": { + "description": "Unique ID of the Heater-Shaker Module.", + "title": "Moduleid", + "type": "string" + } + }, + "required": ["moduleId"], + "title": "WaitForTemperatureParams", + "type": "object" + }, + "opentrons__protocol_engine__commands__temperature_module__set_target_temperature__SetTargetTemperatureCreate": { + "description": "A request to create a Temperature Module's set temperature command.", + "properties": { + "commandType": { + "const": "temperatureModule/setTargetTemperature", + "default": "temperatureModule/setTargetTemperature", + "enum": ["temperatureModule/setTargetTemperature"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/opentrons__protocol_engine__commands__temperature_module__set_target_temperature__SetTargetTemperatureParams" + } + }, + "required": ["params"], + "title": "SetTargetTemperatureCreate", + "type": "object" + }, + "opentrons__protocol_engine__commands__temperature_module__set_target_temperature__SetTargetTemperatureParams": { + "description": "Input parameters to set a Temperature Module's target temperature.", + "properties": { + "celsius": { + "description": "Target temperature in \u00b0C.", + "title": "Celsius", + "type": "number" + }, + "moduleId": { + "description": "Unique ID of the Temperature Module.", + "title": "Moduleid", + "type": "string" + } + }, + "required": ["moduleId", "celsius"], + "title": "SetTargetTemperatureParams", + "type": "object" + }, + "opentrons__protocol_engine__commands__temperature_module__wait_for_temperature__WaitForTemperatureCreate": { + "description": "A request to create a Temperature Module's wait for temperature command.", + "properties": { + "commandType": { + "const": "temperatureModule/waitForTemperature", + "default": "temperatureModule/waitForTemperature", + "enum": ["temperatureModule/waitForTemperature"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/opentrons__protocol_engine__commands__temperature_module__wait_for_temperature__WaitForTemperatureParams" + } + }, + "required": ["params"], + "title": "WaitForTemperatureCreate", + "type": "object" + }, + "opentrons__protocol_engine__commands__temperature_module__wait_for_temperature__WaitForTemperatureParams": { + "description": "Input parameters to wait for a Temperature Module's target temperature.", + "properties": { + "celsius": { + "description": "Target temperature in \u00b0C. If not specified, will default to the module's target temperature. Specifying a celsius parameter other than the target temperature could lead to unpredictable behavior and hence is not recommended for use. This parameter can be removed in a future version without prior notice.", + "title": "Celsius", + "type": "number" + }, + "moduleId": { + "description": "Unique ID of the Temperature Module.", + "title": "Moduleid", + "type": "string" + } + }, + "required": ["moduleId"], + "title": "WaitForTemperatureParams", + "type": "object" + }, + "opentrons__protocol_engine__commands__thermocycler__close_lid__CloseLidCreate": { + "description": "A request to close a Thermocycler's lid.", + "properties": { + "commandType": { + "const": "thermocycler/closeLid", + "default": "thermocycler/closeLid", + "enum": ["thermocycler/closeLid"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/opentrons__protocol_engine__commands__thermocycler__close_lid__CloseLidParams" + } + }, + "required": ["params"], + "title": "CloseLidCreate", + "type": "object" + }, + "opentrons__protocol_engine__commands__thermocycler__close_lid__CloseLidParams": { + "description": "Input parameters to close a Thermocycler's lid.", + "properties": { + "moduleId": { + "description": "Unique ID of the Thermocycler.", + "title": "Moduleid", + "type": "string" + } + }, + "required": ["moduleId"], + "title": "CloseLidParams", + "type": "object" + }, + "opentrons__protocol_engine__commands__thermocycler__open_lid__OpenLidCreate": { + "description": "A request to open a Thermocycler's lid.", + "properties": { + "commandType": { + "const": "thermocycler/openLid", + "default": "thermocycler/openLid", + "enum": ["thermocycler/openLid"], + "title": "Commandtype", + "type": "string" + }, + "intent": { + "$ref": "#/$defs/CommandIntent", + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "title": "Intent" + }, + "key": { + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "title": "Key", + "type": "string" + }, + "params": { + "$ref": "#/$defs/opentrons__protocol_engine__commands__thermocycler__open_lid__OpenLidParams" + } + }, + "required": ["params"], + "title": "OpenLidCreate", + "type": "object" + }, + "opentrons__protocol_engine__commands__thermocycler__open_lid__OpenLidParams": { + "description": "Input parameters to open a Thermocycler's lid.", + "properties": { + "moduleId": { + "description": "Unique ID of the Thermocycler.", + "title": "Moduleid", + "type": "string" + } + }, + "required": ["moduleId"], + "title": "OpenLidParams", + "type": "object" + } + }, + "$id": "opentronsCommandSchemaV12", + "$schema": "http://json-schema.org/draft-07/schema#", + "discriminator": { + "mapping": { + "absorbanceReader/closeLid": "#/$defs/opentrons__protocol_engine__commands__absorbance_reader__close_lid__CloseLidCreate", + "absorbanceReader/initialize": "#/$defs/InitializeCreate", + "absorbanceReader/openLid": "#/$defs/opentrons__protocol_engine__commands__absorbance_reader__open_lid__OpenLidCreate", + "absorbanceReader/read": "#/$defs/ReadAbsorbanceCreate", + "airGapInPlace": "#/$defs/AirGapInPlaceCreate", + "aspirate": "#/$defs/AspirateCreate", + "aspirateInPlace": "#/$defs/AspirateInPlaceCreate", + "aspirateWhileTracking": "#/$defs/AspirateWhileTrackingCreate", + "blowOutInPlace": "#/$defs/BlowOutInPlaceCreate", + "blowout": "#/$defs/BlowOutCreate", + "calibration/calibrateGripper": "#/$defs/CalibrateGripperCreate", + "calibration/calibrateModule": "#/$defs/CalibrateModuleCreate", + "calibration/calibratePipette": "#/$defs/CalibratePipetteCreate", + "calibration/moveToMaintenancePosition": "#/$defs/MoveToMaintenancePositionCreate", + "comment": "#/$defs/CommentCreate", + "configureForVolume": "#/$defs/ConfigureForVolumeCreate", + "configureNozzleLayout": "#/$defs/ConfigureNozzleLayoutCreate", + "custom": "#/$defs/CustomCreate", + "dispense": "#/$defs/DispenseCreate", + "dispenseInPlace": "#/$defs/DispenseInPlaceCreate", + "dispenseWhileTracking": "#/$defs/DispenseWhileTrackingCreate", + "dropTip": "#/$defs/DropTipCreate", + "dropTipInPlace": "#/$defs/DropTipInPlaceCreate", + "flexStacker/configure": "#/$defs/ConfigureCreate", + "flexStacker/retrieve": "#/$defs/RetrieveCreate", + "flexStacker/store": "#/$defs/StoreCreate", + "getNextTip": "#/$defs/GetNextTipCreate", + "getTipPresence": "#/$defs/GetTipPresenceCreate", + "heaterShaker/closeLabwareLatch": "#/$defs/CloseLabwareLatchCreate", + "heaterShaker/deactivateHeater": "#/$defs/DeactivateHeaterCreate", + "heaterShaker/deactivateShaker": "#/$defs/DeactivateShakerCreate", + "heaterShaker/openLabwareLatch": "#/$defs/OpenLabwareLatchCreate", + "heaterShaker/setAndWaitForShakeSpeed": "#/$defs/SetAndWaitForShakeSpeedCreate", + "heaterShaker/setTargetTemperature": "#/$defs/opentrons__protocol_engine__commands__heater_shaker__set_target_temperature__SetTargetTemperatureCreate", + "heaterShaker/waitForTemperature": "#/$defs/opentrons__protocol_engine__commands__heater_shaker__wait_for_temperature__WaitForTemperatureCreate", + "home": "#/$defs/HomeCreate", + "liquidProbe": "#/$defs/LiquidProbeCreate", + "loadLabware": "#/$defs/LoadLabwareCreate", + "loadLid": "#/$defs/LoadLidCreate", + "loadLidStack": "#/$defs/LoadLidStackCreate", + "loadLiquid": "#/$defs/LoadLiquidCreate", + "loadLiquidClass": "#/$defs/LoadLiquidClassCreate", + "loadModule": "#/$defs/LoadModuleCreate", + "loadPipette": "#/$defs/LoadPipetteCreate", + "magneticModule/disengage": "#/$defs/DisengageCreate", + "magneticModule/engage": "#/$defs/EngageCreate", + "moveLabware": "#/$defs/MoveLabwareCreate", + "moveRelative": "#/$defs/MoveRelativeCreate", + "moveToAddressableArea": "#/$defs/MoveToAddressableAreaCreate", + "moveToAddressableAreaForDropTip": "#/$defs/MoveToAddressableAreaForDropTipCreate", + "moveToCoordinates": "#/$defs/MoveToCoordinatesCreate", + "moveToWell": "#/$defs/MoveToWellCreate", + "pause": "#/$defs/WaitForResumeCreate", + "pickUpTip": "#/$defs/PickUpTipCreate", + "prepareToAspirate": "#/$defs/PrepareToAspirateCreate", + "reloadLabware": "#/$defs/ReloadLabwareCreate", + "retractAxis": "#/$defs/RetractAxisCreate", + "robot/closeGripperJaw": "#/$defs/closeGripperJawCreate", + "robot/moveAxesRelative": "#/$defs/MoveAxesRelativeCreate", + "robot/moveAxesTo": "#/$defs/MoveAxesToCreate", + "robot/moveTo": "#/$defs/MoveToCreate", + "robot/openGripperJaw": "#/$defs/openGripperJawCreate", + "savePosition": "#/$defs/SavePositionCreate", + "setRailLights": "#/$defs/SetRailLightsCreate", + "setStatusBar": "#/$defs/SetStatusBarCreate", + "temperatureModule/deactivate": "#/$defs/DeactivateTemperatureCreate", + "temperatureModule/setTargetTemperature": "#/$defs/opentrons__protocol_engine__commands__temperature_module__set_target_temperature__SetTargetTemperatureCreate", + "temperatureModule/waitForTemperature": "#/$defs/opentrons__protocol_engine__commands__temperature_module__wait_for_temperature__WaitForTemperatureCreate", + "thermocycler/closeLid": "#/$defs/opentrons__protocol_engine__commands__thermocycler__close_lid__CloseLidCreate", + "thermocycler/deactivateBlock": "#/$defs/DeactivateBlockCreate", + "thermocycler/deactivateLid": "#/$defs/DeactivateLidCreate", + "thermocycler/openLid": "#/$defs/opentrons__protocol_engine__commands__thermocycler__open_lid__OpenLidCreate", + "thermocycler/runExtendedProfile": "#/$defs/RunExtendedProfileCreate", + "thermocycler/runProfile": "#/$defs/RunProfileCreate", + "thermocycler/setTargetBlockTemperature": "#/$defs/SetTargetBlockTemperatureCreate", + "thermocycler/setTargetLidTemperature": "#/$defs/SetTargetLidTemperatureCreate", + "thermocycler/waitForBlockTemperature": "#/$defs/WaitForBlockTemperatureCreate", + "thermocycler/waitForLidTemperature": "#/$defs/WaitForLidTemperatureCreate", + "touchTip": "#/$defs/TouchTipCreate", + "tryLiquidProbe": "#/$defs/TryLiquidProbeCreate", + "unsafe/blowOutInPlace": "#/$defs/UnsafeBlowOutInPlaceCreate", + "unsafe/dropTipInPlace": "#/$defs/UnsafeDropTipInPlaceCreate", + "unsafe/engageAxes": "#/$defs/UnsafeEngageAxesCreate", + "unsafe/placeLabware": "#/$defs/UnsafePlaceLabwareCreate", + "unsafe/ungripLabware": "#/$defs/UnsafeUngripLabwareCreate", + "unsafe/updatePositionEstimators": "#/$defs/UpdatePositionEstimatorsCreate", + "verifyTipPresence": "#/$defs/VerifyTipPresenceCreate", + "waitForDuration": "#/$defs/WaitForDurationCreate", + "waitForResume": "#/$defs/WaitForResumeCreate" + }, + "propertyName": "commandType" + }, + "oneOf": [ + { + "$ref": "#/$defs/AirGapInPlaceCreate" + }, + { + "$ref": "#/$defs/AspirateCreate" + }, + { + "$ref": "#/$defs/AspirateWhileTrackingCreate" + }, + { + "$ref": "#/$defs/AspirateInPlaceCreate" + }, + { + "$ref": "#/$defs/CommentCreate" + }, + { + "$ref": "#/$defs/ConfigureForVolumeCreate" + }, + { + "$ref": "#/$defs/ConfigureNozzleLayoutCreate" + }, + { + "$ref": "#/$defs/CustomCreate" + }, + { + "$ref": "#/$defs/DispenseCreate" + }, + { + "$ref": "#/$defs/DispenseInPlaceCreate" + }, + { + "$ref": "#/$defs/DispenseWhileTrackingCreate" + }, + { + "$ref": "#/$defs/BlowOutCreate" + }, + { + "$ref": "#/$defs/BlowOutInPlaceCreate" + }, + { + "$ref": "#/$defs/DropTipCreate" + }, + { + "$ref": "#/$defs/DropTipInPlaceCreate" + }, + { + "$ref": "#/$defs/HomeCreate" + }, + { + "$ref": "#/$defs/RetractAxisCreate" + }, + { + "$ref": "#/$defs/LoadLabwareCreate" + }, + { + "$ref": "#/$defs/ReloadLabwareCreate" + }, + { + "$ref": "#/$defs/LoadLiquidCreate" + }, + { + "$ref": "#/$defs/LoadLiquidClassCreate" + }, + { + "$ref": "#/$defs/LoadModuleCreate" + }, + { + "$ref": "#/$defs/LoadPipetteCreate" + }, + { + "$ref": "#/$defs/LoadLidStackCreate" + }, + { + "$ref": "#/$defs/LoadLidCreate" + }, + { + "$ref": "#/$defs/MoveLabwareCreate" + }, + { + "$ref": "#/$defs/MoveRelativeCreate" + }, + { + "$ref": "#/$defs/MoveToCoordinatesCreate" + }, + { + "$ref": "#/$defs/MoveToWellCreate" + }, + { + "$ref": "#/$defs/MoveToAddressableAreaCreate" + }, + { + "$ref": "#/$defs/MoveToAddressableAreaForDropTipCreate" + }, + { + "$ref": "#/$defs/PrepareToAspirateCreate" + }, + { + "$ref": "#/$defs/WaitForResumeCreate" + }, + { + "$ref": "#/$defs/WaitForDurationCreate" + }, + { + "$ref": "#/$defs/PickUpTipCreate" + }, + { + "$ref": "#/$defs/SavePositionCreate" + }, + { + "$ref": "#/$defs/SetRailLightsCreate" + }, + { + "$ref": "#/$defs/TouchTipCreate" + }, + { + "$ref": "#/$defs/SetStatusBarCreate" + }, + { + "$ref": "#/$defs/VerifyTipPresenceCreate" + }, + { + "$ref": "#/$defs/GetTipPresenceCreate" + }, + { + "$ref": "#/$defs/GetNextTipCreate" + }, + { + "$ref": "#/$defs/LiquidProbeCreate" + }, + { + "$ref": "#/$defs/TryLiquidProbeCreate" + }, + { + "$ref": "#/$defs/opentrons__protocol_engine__commands__heater_shaker__wait_for_temperature__WaitForTemperatureCreate" + }, + { + "$ref": "#/$defs/opentrons__protocol_engine__commands__heater_shaker__set_target_temperature__SetTargetTemperatureCreate" + }, + { + "$ref": "#/$defs/DeactivateHeaterCreate" + }, + { + "$ref": "#/$defs/SetAndWaitForShakeSpeedCreate" + }, + { + "$ref": "#/$defs/DeactivateShakerCreate" + }, + { + "$ref": "#/$defs/OpenLabwareLatchCreate" + }, + { + "$ref": "#/$defs/CloseLabwareLatchCreate" + }, + { + "$ref": "#/$defs/DisengageCreate" + }, + { + "$ref": "#/$defs/EngageCreate" + }, + { + "$ref": "#/$defs/opentrons__protocol_engine__commands__temperature_module__set_target_temperature__SetTargetTemperatureCreate" + }, + { + "$ref": "#/$defs/opentrons__protocol_engine__commands__temperature_module__wait_for_temperature__WaitForTemperatureCreate" + }, + { + "$ref": "#/$defs/DeactivateTemperatureCreate" + }, + { + "$ref": "#/$defs/SetTargetBlockTemperatureCreate" + }, + { + "$ref": "#/$defs/WaitForBlockTemperatureCreate" + }, + { + "$ref": "#/$defs/SetTargetLidTemperatureCreate" + }, + { + "$ref": "#/$defs/WaitForLidTemperatureCreate" + }, + { + "$ref": "#/$defs/DeactivateBlockCreate" + }, + { + "$ref": "#/$defs/DeactivateLidCreate" + }, + { + "$ref": "#/$defs/opentrons__protocol_engine__commands__thermocycler__open_lid__OpenLidCreate" + }, + { + "$ref": "#/$defs/opentrons__protocol_engine__commands__thermocycler__close_lid__CloseLidCreate" + }, + { + "$ref": "#/$defs/RunProfileCreate" + }, + { + "$ref": "#/$defs/RunExtendedProfileCreate" + }, + { + "$ref": "#/$defs/opentrons__protocol_engine__commands__absorbance_reader__close_lid__CloseLidCreate" + }, + { + "$ref": "#/$defs/opentrons__protocol_engine__commands__absorbance_reader__open_lid__OpenLidCreate" + }, + { + "$ref": "#/$defs/InitializeCreate" + }, + { + "$ref": "#/$defs/ReadAbsorbanceCreate" + }, + { + "$ref": "#/$defs/ConfigureCreate" + }, + { + "$ref": "#/$defs/RetrieveCreate" + }, + { + "$ref": "#/$defs/StoreCreate" + }, + { + "$ref": "#/$defs/CalibrateGripperCreate" + }, + { + "$ref": "#/$defs/CalibratePipetteCreate" + }, + { + "$ref": "#/$defs/CalibrateModuleCreate" + }, + { + "$ref": "#/$defs/MoveToMaintenancePositionCreate" + }, + { + "$ref": "#/$defs/UnsafeBlowOutInPlaceCreate" + }, + { + "$ref": "#/$defs/UnsafeDropTipInPlaceCreate" + }, + { + "$ref": "#/$defs/UpdatePositionEstimatorsCreate" + }, + { + "$ref": "#/$defs/UnsafeEngageAxesCreate" + }, + { + "$ref": "#/$defs/UnsafeUngripLabwareCreate" + }, + { + "$ref": "#/$defs/UnsafePlaceLabwareCreate" + }, + { + "$ref": "#/$defs/MoveAxesRelativeCreate" + }, + { + "$ref": "#/$defs/MoveAxesToCreate" + }, + { + "$ref": "#/$defs/MoveToCreate" + }, + { + "$ref": "#/$defs/openGripperJawCreate" + }, + { + "$ref": "#/$defs/closeGripperJawCreate" + } + ] +} From c630b883101e98e79bccdea70fc9de5b16a27f4a Mon Sep 17 00:00:00 2001 From: Nick Diehl <47604184+ncdiehl11@users.noreply.github.com> Date: Tue, 28 Jan 2025 14:56:15 -0500 Subject: [PATCH 07/22] fix(protocol-designer): set PathField width to 100% (#17370) Fixes width of `PathField` `PathButton` used in move liquid step form --- .../ProtocolSteps/StepForm/PipetteFields/PathField.tsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/PipetteFields/PathField.tsx b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/PipetteFields/PathField.tsx index 691706a2884..86824e122cd 100644 --- a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/PipetteFields/PathField.tsx +++ b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/PipetteFields/PathField.tsx @@ -69,7 +69,7 @@ interface PathButtonProps { } function PathButton(props: PathButtonProps): JSX.Element { - const { disabled, onClick, id, path, selected, subtitle } = props + const { disabled, onClick, path, selected, subtitle } = props const [targetProps, tooltipProps] = useHoverTooltip({ placement: TOOLTIP_TOP_START, }) @@ -79,14 +79,18 @@ function PathButton(props: PathButtonProps): JSX.Element { {t(`step_edit_form.field.path.title.${path}`)} - + path animation {subtitle} ) return ( - + {tooltip} Date: Tue, 28 Jan 2025 15:10:48 -0500 Subject: [PATCH 08/22] fix(protocol-designer): update logic to add modules and fixtures with plate reader (#17344) * fix(protocol-designer): update logic to add modules and fixtures with plate reader --- .../SelectFixtures.tsx | 27 ++++++-- .../CreateNewProtocolWizard/SelectModules.tsx | 8 ++- .../__tests__/utils.test.ts | 58 ++++++++++++++++- .../CreateNewProtocolWizard/constants.ts | 2 +- .../pages/CreateNewProtocolWizard/index.tsx | 16 ++++- .../pages/CreateNewProtocolWizard/utils.tsx | 65 +++++++++++-------- 6 files changed, 138 insertions(+), 38 deletions(-) diff --git a/protocol-designer/src/pages/CreateNewProtocolWizard/SelectFixtures.tsx b/protocol-designer/src/pages/CreateNewProtocolWizard/SelectFixtures.tsx index 400da9a6235..19eb12cb2db 100644 --- a/protocol-designer/src/pages/CreateNewProtocolWizard/SelectFixtures.tsx +++ b/protocol-designer/src/pages/CreateNewProtocolWizard/SelectFixtures.tsx @@ -70,6 +70,15 @@ export function SelectFixtures(props: WizardTileProps): JSX.Element | null { subHeader={t('fixtures_replace')} disabled={!hasTrash} goBack={() => { + // Note this is avoid the following case issue. + // https://github.com/Opentrons/opentrons/pull/17344#pullrequestreview-2576591908 + setValue( + 'additionalEquipment', + additionalEquipment.filter( + ae => ae === 'gripper' || ae === 'trashBin' + ) + ) + goBack(1) }} proceed={handleProceed} @@ -135,11 +144,18 @@ export function SelectFixtures(props: WizardTileProps): JSX.Element | null { filterOptions: getNumOptions( numSlotsAvailable >= MAX_SLOTS ? MAX_SLOTS - : numSlotsAvailable + numStagingAreas + : numSlotsAvailable ), onClick: (value: string) => { const inputNum = parseInt(value) - let updatedStagingAreas = [...additionalEquipment] + const currentStagingAreas = additionalEquipment.filter( + additional => additional === 'stagingArea' + ) + const otherEquipment = additionalEquipment.filter( + additional => additional !== 'stagingArea' + ) + let updatedStagingAreas = currentStagingAreas + // let updatedStagingAreas = [...additionalEquipment] if (inputNum > numStagingAreas) { const difference = inputNum - numStagingAreas @@ -148,13 +164,16 @@ export function SelectFixtures(props: WizardTileProps): JSX.Element | null { ...Array(difference).fill(ae), ] } else { - updatedStagingAreas = updatedStagingAreas.slice( + updatedStagingAreas = currentStagingAreas.slice( 0, inputNum ) } - setValue('additionalEquipment', updatedStagingAreas) + setValue('additionalEquipment', [ + ...otherEquipment, + ...updatedStagingAreas, + ]) }, } return ( diff --git a/protocol-designer/src/pages/CreateNewProtocolWizard/SelectModules.tsx b/protocol-designer/src/pages/CreateNewProtocolWizard/SelectModules.tsx index 8365c62de5a..19e757ee0dc 100644 --- a/protocol-designer/src/pages/CreateNewProtocolWizard/SelectModules.tsx +++ b/protocol-designer/src/pages/CreateNewProtocolWizard/SelectModules.tsx @@ -178,6 +178,7 @@ export function SelectModules(props: WizardTileProps): JSX.Element | null { ) : null} {filteredSupportedModules + .sort((moduleA, moduleB) => moduleA.localeCompare(moduleB)) .filter(module => enableAbsorbanceReader ? module @@ -219,6 +220,9 @@ export function SelectModules(props: WizardTileProps): JSX.Element | null { gridGap={SPACING.spacing4} > {Object.entries(modules) + .sort(([, moduleA], [, moduleB]) => + moduleA.model.localeCompare(moduleB.model) + ) .reduce>( (acc, [key, module]) => { const existingModule = acc.find( @@ -253,7 +257,9 @@ export function SelectModules(props: WizardTileProps): JSX.Element | null { }, dropdownType: 'neutral' as DropdownBorder, filterOptions: getNumOptions( - numSlotsAvailable + module.count + module.model !== ABSORBANCE_READER_V1 + ? numSlotsAvailable + module.count + : numSlotsAvailable ), } return ( diff --git a/protocol-designer/src/pages/CreateNewProtocolWizard/__tests__/utils.test.ts b/protocol-designer/src/pages/CreateNewProtocolWizard/__tests__/utils.test.ts index bda3d71da18..a167217bf25 100644 --- a/protocol-designer/src/pages/CreateNewProtocolWizard/__tests__/utils.test.ts +++ b/protocol-designer/src/pages/CreateNewProtocolWizard/__tests__/utils.test.ts @@ -1,14 +1,19 @@ import { it, describe, expect } from 'vitest' import { FLEX_ROBOT_TYPE, + ABSORBANCE_READER_V1, + ABSORBANCE_READER_TYPE, HEATERSHAKER_MODULE_TYPE, HEATERSHAKER_MODULE_V1, MAGNETIC_BLOCK_TYPE, MAGNETIC_BLOCK_V1, + MAGNETIC_MODULE_V1, + MAGNETIC_MODULE_V2, TEMPERATURE_MODULE_TYPE, TEMPERATURE_MODULE_V1, TEMPERATURE_MODULE_V2, THERMOCYCLER_MODULE_TYPE, + THERMOCYCLER_MODULE_V1, THERMOCYCLER_MODULE_V2, } from '@opentrons/shared-data' import { getNumSlotsAvailable, getTrashSlot } from '../utils' @@ -36,18 +41,60 @@ describe('getNumSlotsAvailable', () => { const result = getNumSlotsAvailable(null, [], 'gripper') expect(result).toBe(0) }) - it('should return 1 for a non MoaM module', () => { + + it('should return 1 for a non MoaM module - temperature module', () => { const result = getNumSlotsAvailable(null, [], TEMPERATURE_MODULE_V1) expect(result).toBe(1) }) + + it('should return 1 for a non MoaM module - absorbance plate reader', () => { + const result = getNumSlotsAvailable(null, [], ABSORBANCE_READER_V1) + expect(result).toBe(1) + }) + + it('should return 1 for a non MoaM module - thermocycler v1', () => { + const result = getNumSlotsAvailable(null, [], THERMOCYCLER_MODULE_V1) + expect(result).toBe(1) + }) + + it('should return 1 for a non MoaM module - magnetic module v1', () => { + const result = getNumSlotsAvailable(null, [], MAGNETIC_MODULE_V1) + expect(result).toBe(1) + }) + + it('should return 1 for a non MoaM module - magnetic module v2', () => { + const result = getNumSlotsAvailable(null, [], MAGNETIC_MODULE_V2) + expect(result).toBe(1) + }) + it('should return 2 for a thermocycler', () => { const result = getNumSlotsAvailable(null, [], THERMOCYCLER_MODULE_V2) expect(result).toBe(2) }) + it('should return 8 when there are no modules or additional equipment for a heater-shaker', () => { const result = getNumSlotsAvailable(null, [], HEATERSHAKER_MODULE_V1) expect(result).toBe(8) }) + + it('should return 3 when there a plate reader', () => { + const mockModules = { + 0: { + model: ABSORBANCE_READER_V1, + type: ABSORBANCE_READER_TYPE, + slot: 'B3', + }, + } + const mockAdditionalEquipment: AdditionalEquipment[] = ['trashBin'] + const result = getNumSlotsAvailable( + mockModules, + mockAdditionalEquipment, + 'stagingArea' + ) + // Note: the return value is 3 because trashBin can be placed slot1 and plate reader is on B3 + expect(result).toBe(3) + }) + it('should return 0 when there is a TC and 7 modules for a temperature module v2', () => { const mockModules = { 0: { @@ -90,6 +137,7 @@ describe('getNumSlotsAvailable', () => { const result = getNumSlotsAvailable(mockModules, [], TEMPERATURE_MODULE_V2) expect(result).toBe(0) }) + it('should return 1 when there are 9 additional equipment and 1 is a waste chute on the staging area and one is a gripper for a heater-shaker', () => { const mockAdditionalEquipment: AdditionalEquipment[] = [ 'trashBin', @@ -109,6 +157,7 @@ describe('getNumSlotsAvailable', () => { ) expect(result).toBe(1) }) + it('should return 1 when there is a full deck but one staging area for waste chute', () => { const mockModules = { 0: { @@ -148,6 +197,7 @@ describe('getNumSlotsAvailable', () => { ) expect(result).toBe(1) }) + it('should return 1 when there are 7 modules (with one magnetic block) and one trash for staging area', () => { const mockModules = { 0: { @@ -187,8 +237,10 @@ describe('getNumSlotsAvailable', () => { mockAdditionalEquipment, 'stagingArea' ) - expect(result).toBe(1) + // Note: the return value is 2 because trashBin can be placed slot1 + expect(result).toBe(2) }) + it('should return 1 when there are 8 modules with 2 magnetic blocks and one trash for staging area', () => { const mockModules = { 0: { @@ -233,7 +285,7 @@ describe('getNumSlotsAvailable', () => { mockAdditionalEquipment, 'stagingArea' ) - expect(result).toBe(1) + expect(result).toBe(2) }) it('should return 4 when there are 12 magnetic blocks for staging area', () => { const mockModules = { diff --git a/protocol-designer/src/pages/CreateNewProtocolWizard/constants.ts b/protocol-designer/src/pages/CreateNewProtocolWizard/constants.ts index 6e762e48f0a..5e1179c58f4 100644 --- a/protocol-designer/src/pages/CreateNewProtocolWizard/constants.ts +++ b/protocol-designer/src/pages/CreateNewProtocolWizard/constants.ts @@ -127,7 +127,7 @@ export const DEFAULT_SLOT_MAP_FLEX: { [HEATERSHAKER_MODULE_V1]: 'D1', [MAGNETIC_BLOCK_V1]: 'D2', [TEMPERATURE_MODULE_V2]: 'C1', - [ABSORBANCE_READER_V1]: 'D3', + [ABSORBANCE_READER_V1]: 'B3', } export const DEFAULT_SLOT_MAP_OT2: { [moduleType in ModuleType]?: string } = { diff --git a/protocol-designer/src/pages/CreateNewProtocolWizard/index.tsx b/protocol-designer/src/pages/CreateNewProtocolWizard/index.tsx index d3451605756..2e29273b9ac 100644 --- a/protocol-designer/src/pages/CreateNewProtocolWizard/index.tsx +++ b/protocol-designer/src/pages/CreateNewProtocolWizard/index.tsx @@ -12,6 +12,7 @@ import { useNavigate } from 'react-router-dom' import { FLEX_ROBOT_TYPE, getAreSlotsAdjacent, + ABSORBANCE_READER_MODELS, HEATERSHAKER_MODULE_TYPE, MAGNETIC_BLOCK_TYPE, MAGNETIC_MODULE_TYPE, @@ -283,11 +284,20 @@ export function CreateNewProtocolWizard(): JSX.Element | null { const stagingAreas = values.additionalEquipment.filter( equipment => equipment === 'stagingArea' ) + if (stagingAreas.length > 0) { + // Note: when plate reader is present, cutoutB3 is not available for StagingArea + const hasPlateReader = modules.some( + module => module.model === ABSORBANCE_READER_MODELS[0] + ) stagingAreas.forEach((_, index) => { - return dispatch( - createDeckFixture('stagingArea', STAGING_AREA_CUTOUTS_ORDERED[index]) - ) + const stagingAreaCutout = hasPlateReader + ? STAGING_AREA_CUTOUTS_ORDERED.filter( + cutout => cutout !== 'cutoutB3' + )[index] + : STAGING_AREA_CUTOUTS_ORDERED[index] + + return dispatch(createDeckFixture('stagingArea', stagingAreaCutout)) }) } diff --git a/protocol-designer/src/pages/CreateNewProtocolWizard/utils.tsx b/protocol-designer/src/pages/CreateNewProtocolWizard/utils.tsx index 3ffb60d10f2..69abb7e6ae7 100644 --- a/protocol-designer/src/pages/CreateNewProtocolWizard/utils.tsx +++ b/protocol-designer/src/pages/CreateNewProtocolWizard/utils.tsx @@ -30,10 +30,11 @@ import type { import type { DropdownOption } from '@opentrons/components' import type { AdditionalEquipment, WizardFormState } from './types' -const TOTAL_OUTER_SLOTS = 8 -const MIDDLE_SLOT_NUM = 4 -const MAX_MAGNETIC_BLOCK_SLOTS = 12 -const TOTAL_LEFT_SLOTS = 4 +const NUM_SLOTS_OUTER = 8 +const NUM_SLOTS_MIDDLE = 4 +const NUM_SLOTS_COLUMN3 = 4 +const NUM_SLOTS_MAGNETIC_BLOCK = 12 + export const getNumOptions = (length: number): DropdownOption[] => { return Array.from({ length }, (_, i) => ({ name: `${i + 1}`, @@ -66,12 +67,12 @@ export const getNumSlotsAvailable = ( const magneticBlockCount = magneticBlocks.length const moduleCount = modules != null ? Object.keys(modules).length : 0 let filteredModuleLength = moduleCount - if (magneticBlockCount <= MIDDLE_SLOT_NUM) { + if (magneticBlockCount <= NUM_SLOTS_MIDDLE) { // Subtract magnetic blocks directly if their count is ≤ 4 filteredModuleLength -= magneticBlockCount } else { // Subtract the excess magnetic blocks beyond 4 - const extraMagneticBlocks = magneticBlockCount - MIDDLE_SLOT_NUM + const extraMagneticBlocks = magneticBlockCount - NUM_SLOTS_MIDDLE filteredModuleLength -= extraMagneticBlocks } if (hasTC) { @@ -86,11 +87,9 @@ export const getNumSlotsAvailable = ( case 'gripper': { return 0 } - // TODO: wire up absorbance reader - case ABSORBANCE_READER_V1: { - return 1 - } + // these modules don't support MoaM + case ABSORBANCE_READER_V1: case THERMOCYCLER_MODULE_V1: case TEMPERATURE_MODULE_V1: case MAGNETIC_MODULE_V1: @@ -105,43 +104,45 @@ export const getNumSlotsAvailable = ( return 2 } } + case 'trashBin': case HEATERSHAKER_MODULE_V1: case TEMPERATURE_MODULE_V2: { return ( - TOTAL_OUTER_SLOTS - + NUM_SLOTS_OUTER - (filteredModuleLength + filteredAdditionalEquipmentLength) ) } case 'stagingArea': { - const lengthMinusMagneticBlock = - moduleCount + (hasTC ? 1 : 0) - magneticBlockCount - let adjustedModuleLength = 0 - if (lengthMinusMagneticBlock > TOTAL_LEFT_SLOTS) { - adjustedModuleLength = lengthMinusMagneticBlock - TOTAL_LEFT_SLOTS - } - - const occupiedSlots = - adjustedModuleLength + filteredAdditionalEquipmentLength - - return TOTAL_LEFT_SLOTS - occupiedSlots + const modulesWithColumn3 = + modules !== null + ? Object.values(modules).filter(module => module.slot?.includes('3')) + .length + : 0 + const fixtureSlotsWithColumn3 = + additionalEquipment !== null + ? additionalEquipment.filter(slot => slot.includes('3')).length + : 0 + return NUM_SLOTS_COLUMN3 - modulesWithColumn3 - fixtureSlotsWithColumn3 } + case 'wasteChute': { const adjustmentForStagingArea = numStagingAreas >= 1 ? 1 : 0 return ( - TOTAL_OUTER_SLOTS - + NUM_SLOTS_OUTER - (filteredModuleLength + filteredAdditionalEquipmentLength - adjustmentForStagingArea) ) } + case MAGNETIC_BLOCK_V1: { const filteredAdditionalEquipmentForMagneticBlockLength = additionalEquipment.filter( ae => ae !== 'gripper' && ae !== 'stagingArea' )?.length return ( - MAX_MAGNETIC_BLOCK_SLOTS - + NUM_SLOTS_MAGNETIC_BLOCK - (filteredModuleLength + filteredAdditionalEquipmentForMagneticBlockLength) ) @@ -292,9 +293,21 @@ export const getTrashSlot = (values: WizardFormState): string => { equipment.includes('stagingArea') ) - const cutouts = stagingAreas.map( - (_, index) => STAGING_AREA_CUTOUTS_ORDERED[index] + // when plate reader is present, cutoutB3 is not available for StagingArea + const hasPlateReader = + modules !== null + ? Object.values(modules).some( + module => module.model === ABSORBANCE_READER_V1 + ) + : false + const cutouts = stagingAreas.map((_, index) => + hasPlateReader + ? STAGING_AREA_CUTOUTS_ORDERED.filter(cutout => cutout !== 'cutoutB3')[ + index + ] + : STAGING_AREA_CUTOUTS_ORDERED[index] ) + const hasWasteChute = additionalEquipment.find(equipment => equipment.includes('wasteChute') ) From 5bd8f03c8eb0818196d21b10241ec690c8a85832 Mon Sep 17 00:00:00 2001 From: Nick Diehl <47604184+ncdiehl11@users.noreply.github.com> Date: Tue, 28 Jan 2025 16:28:24 -0500 Subject: [PATCH 09/22] fix(components,-protocol-designer): fix ToggleStepFormField style, realign step title (#17372) This PR makes two small style changes: 1) fixes disabled style for ToggleStepFormField (and ListButton by implication), and 2) aligns the protocol step title to the center of its container. --- components/src/atoms/ListButton/index.tsx | 12 +++--- .../molecules/ToggleStepFormField/index.tsx | 41 ++++++++++--------- .../pages/Designer/ProtocolSteps/index.tsx | 5 ++- 3 files changed, 33 insertions(+), 25 deletions(-) diff --git a/components/src/atoms/ListButton/index.tsx b/components/src/atoms/ListButton/index.tsx index fd4d0cce052..610c76bb7a9 100644 --- a/components/src/atoms/ListButton/index.tsx +++ b/components/src/atoms/ListButton/index.tsx @@ -2,7 +2,7 @@ import { css } from 'styled-components' import { Flex } from '../../primitives' import { SPACING } from '../../ui-style-constants' import { BORDERS, COLORS } from '../../helix-design-system' -import { CURSOR_POINTER } from '../../styles' +import { CURSOR_DEFAULT, CURSOR_POINTER } from '../../styles' import type { ReactNode } from 'react' import type { StyleProps } from '../../primitives' @@ -42,13 +42,13 @@ const LISTBUTTON_PROPS_BY_TYPE: Record< odd stylings **/ export function ListButton(props: ListButtonProps): JSX.Element { - const { type, children, disabled, onClick, ...styleProps } = props + const { type, children, disabled = false, onClick, ...styleProps } = props const listButtonProps = LISTBUTTON_PROPS_BY_TYPE[type] const LIST_BUTTON_STYLE = css` - cursor: ${CURSOR_POINTER}; + cursor: ${disabled ? CURSOR_DEFAULT : CURSOR_POINTER}; background-color: ${disabled - ? COLORS.grey35 + ? COLORS.grey20 : listButtonProps.backgroundColor}; max-width: 26.875rem; padding: ${styleProps.padding ?? @@ -56,7 +56,9 @@ export function ListButton(props: ListButtonProps): JSX.Element { border-radius: ${BORDERS.borderRadius8}; &:hover { - background-color: ${listButtonProps.hoverBackgroundColor}; + background-color: ${disabled + ? COLORS.grey20 + : listButtonProps.hoverBackgroundColor}; } ` diff --git a/protocol-designer/src/molecules/ToggleStepFormField/index.tsx b/protocol-designer/src/molecules/ToggleStepFormField/index.tsx index bf730e2523c..ad609acf0b9 100644 --- a/protocol-designer/src/molecules/ToggleStepFormField/index.tsx +++ b/protocol-designer/src/molecules/ToggleStepFormField/index.tsx @@ -7,7 +7,6 @@ import { ListButton, SPACING, StyledText, - TOOLTIP_BOTTOM, Tooltip, useHoverTooltip, } from '@opentrons/components' @@ -37,9 +36,7 @@ export function ToggleStepFormField( tooltipContent, isDisabled, } = props - const [targetProps, tooltipProps] = useHoverTooltip({ - placement: TOOLTIP_BOTTOM, - }) + const [targetProps, tooltipProps] = useHoverTooltip() return ( <> @@ -47,33 +44,39 @@ export function ToggleStepFormField( type="noActive" padding={SPACING.spacing12} onClick={() => { - toggleUpdateValue(!toggleValue) + if (!isDisabled) { + toggleUpdateValue(!toggleValue) + } }} + disabled={isDisabled} > - + {tooltipContent != null ? ( + {tooltipContent} + ) : null} + + - {title} + + {title} + - {tooltipContent != null ? ( - {tooltipContent} - ) : null} {isSelected ? onLabel : offLabel} - {isDisabled ? null : ( - - )} + diff --git a/protocol-designer/src/pages/Designer/ProtocolSteps/index.tsx b/protocol-designer/src/pages/Designer/ProtocolSteps/index.tsx index 91d6325f39f..e426affd60d 100644 --- a/protocol-designer/src/pages/Designer/ProtocolSteps/index.tsx +++ b/protocol-designer/src/pages/Designer/ProtocolSteps/index.tsx @@ -111,7 +111,10 @@ export function ProtocolSteps(): JSX.Element { gridGap={SPACING.spacing4} /> ) : null} - + {currentStep != null && hoveredTerminalItem == null ? ( {i18n.format(currentStep.stepName, 'capitalize')} From fd9b62832054d4bacdc7ebc789aaa642c87cce34 Mon Sep 17 00:00:00 2001 From: Nick Diehl <47604184+ncdiehl11@users.noreply.github.com> Date: Tue, 28 Jan 2025 16:44:07 -0500 Subject: [PATCH 10/22] fix(protocol-designer): fix no tiprack-related whitescreen (#17373) This PR fixes a PD whitescreen bug where a user tries to create a transfer step wihout a tiprack available on the deck. As a temporary fix, I null check the first tiprack option in `TiprackField` and default to a placeholder string. This prevents a whitescreen, and creates a not-enough-tips timeline error if the step is saved, instructing the user to add tipracks to the deck to fix. Closes RESC-380 --- .../src/assets/localization/en/protocol_steps.json | 1 + .../ProtocolSteps/StepForm/PipetteFields/TiprackField.tsx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/protocol-designer/src/assets/localization/en/protocol_steps.json b/protocol-designer/src/assets/localization/en/protocol_steps.json index 12ebc493447..c92e9cdcb83 100644 --- a/protocol-designer/src/assets/localization/en/protocol_steps.json +++ b/protocol-designer/src/assets/localization/en/protocol_steps.json @@ -73,6 +73,7 @@ "multiAspirate": "Consolidate path", "multiDispense": "Distribute path", "new_location": "New location", + "no_tiprack": "No tiprack available", "off_deck": "Off-Deck", "pause": { "untilResume": "Pausing until manually told to resume", diff --git a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/PipetteFields/TiprackField.tsx b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/PipetteFields/TiprackField.tsx index 17e09db5ec6..e589d3226cb 100644 --- a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/PipetteFields/TiprackField.tsx +++ b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/PipetteFields/TiprackField.tsx @@ -64,7 +64,7 @@ export function TiprackField(props: TiprackFieldProps): JSX.Element { - {tiprackOptions[0].name} + {tiprackOptions[0]?.name ?? t('no_tiprack')} From 24c9b5f8e7fecbc6f32967357cccb7386f9c5b9b Mon Sep 17 00:00:00 2001 From: Nick Diehl <47604184+ncdiehl11@users.noreply.github.com> Date: Tue, 28 Jan 2025 16:45:35 -0500 Subject: [PATCH 11/22] refactor(protocol-designer): remove absorbance reader feature flag (#17366) Remove `OT_PD_ENABLE_ABSORBANCE_READER` feature flag and implementation across PD. Closes AUTH-1322 --- .../src/assets/localization/en/feature_flags.json | 4 ---- protocol-designer/src/feature-flags/reducers.ts | 2 -- protocol-designer/src/feature-flags/selectors.ts | 4 ---- protocol-designer/src/feature-flags/types.ts | 3 +-- .../CreateNewProtocolWizard/SelectModules.tsx | 11 +---------- .../__tests__/SelectModules.test.tsx | 2 -- .../pages/Designer/DeckSetup/DeckSetupTools.tsx | 6 +----- .../src/pages/Designer/DeckSetup/LabwareTools.tsx | 6 +----- .../DeckSetup/__tests__/DeckSetupTools.test.tsx | 2 -- .../Designer/DeckSetup/__tests__/utils.test.ts | 14 +++++++------- .../src/pages/Designer/DeckSetup/utils.ts | 3 +-- .../ProtocolSteps/Timeline/AddStepButton.tsx | 10 ++-------- .../src/step-forms/selectors/index.ts | 5 +---- 13 files changed, 15 insertions(+), 57 deletions(-) diff --git a/protocol-designer/src/assets/localization/en/feature_flags.json b/protocol-designer/src/assets/localization/en/feature_flags.json index 92a074088ba..851f8deb5a9 100644 --- a/protocol-designer/src/assets/localization/en/feature_flags.json +++ b/protocol-designer/src/assets/localization/en/feature_flags.json @@ -12,10 +12,6 @@ "title": "Allow all tip rack options", "description": "Enable selection of all tip racks for each pipette." }, - "OT_PD_ENABLE_ABSORBANCE_READER": { - "title": "Enable absorbance plate reader", - "description": "Enable absorbance plate reader support." - }, "OT_PD_ENABLE_COMMENT": { "title": "Enable comment step", "description": "You can add comments anywhere between timeline steps." diff --git a/protocol-designer/src/feature-flags/reducers.ts b/protocol-designer/src/feature-flags/reducers.ts index 336014c6691..efec2f863dd 100644 --- a/protocol-designer/src/feature-flags/reducers.ts +++ b/protocol-designer/src/feature-flags/reducers.ts @@ -23,8 +23,6 @@ const initialFlags: Flags = { process.env.OT_PD_DISABLE_MODULE_RESTRICTIONS === '1' || false, OT_PD_ALLOW_ALL_TIPRACKS: process.env.OT_PD_ALLOW_ALL_TIPRACKS === '1' || false, - OT_PD_ENABLE_ABSORBANCE_READER: - process.env.OT_PD_ENABLE_ABSORBANCE_READER === '1' || false, OT_PD_ENABLE_COMMENT: process.env.OT_PD_ENABLE_COMMENT === '1' || false, OT_PD_ENABLE_RETURN_TIP: process.env.OT_PD_ENABLE_RETURN_TIP === '1' || false, OT_PD_ENABLE_HOT_KEYS_DISPLAY: diff --git a/protocol-designer/src/feature-flags/selectors.ts b/protocol-designer/src/feature-flags/selectors.ts index 6b8a70f8b30..d673ad6bf09 100644 --- a/protocol-designer/src/feature-flags/selectors.ts +++ b/protocol-designer/src/feature-flags/selectors.ts @@ -25,10 +25,6 @@ export const getAllowAllTipracks: Selector = createSelector( getFeatureFlagData, flags => flags.OT_PD_ALLOW_ALL_TIPRACKS ?? false ) -export const getEnableAbsorbanceReader: Selector = createSelector( - getFeatureFlagData, - flags => flags.OT_PD_ENABLE_ABSORBANCE_READER ?? false -) export const getEnableComment: Selector = createSelector( getFeatureFlagData, flags => flags.OT_PD_ENABLE_COMMENT ?? false diff --git a/protocol-designer/src/feature-flags/types.ts b/protocol-designer/src/feature-flags/types.ts index 6840786d149..53ea6615c8b 100644 --- a/protocol-designer/src/feature-flags/types.ts +++ b/protocol-designer/src/feature-flags/types.ts @@ -25,13 +25,13 @@ export const DEPRECATED_FLAGS = [ 'OT_PD_ENABLE_MULTI_TIP', 'OT_PD_ENABLE_MOAM', 'OT_PD_ENABLE_REDESIGN', + 'OT_PD_ENABLE_ABSORBANCE_READER', ] // union of feature flag string constant IDs export type FlagTypes = | 'PRERELEASE_MODE' | 'OT_PD_DISABLE_MODULE_RESTRICTIONS' | 'OT_PD_ALLOW_ALL_TIPRACKS' - | 'OT_PD_ENABLE_ABSORBANCE_READER' | 'OT_PD_ENABLE_COMMENT' | 'OT_PD_ENABLE_RETURN_TIP' | 'OT_PD_ENABLE_HOT_KEYS_DISPLAY' @@ -46,7 +46,6 @@ export const userFacingFlags: FlagTypes[] = [ export const allFlags: FlagTypes[] = [ ...userFacingFlags, 'PRERELEASE_MODE', - 'OT_PD_ENABLE_ABSORBANCE_READER', 'OT_PD_ENABLE_COMMENT', 'OT_PD_ENABLE_RETURN_TIP', 'OT_PD_ENABLE_REACT_SCAN', diff --git a/protocol-designer/src/pages/CreateNewProtocolWizard/SelectModules.tsx b/protocol-designer/src/pages/CreateNewProtocolWizard/SelectModules.tsx index 19e757ee0dc..717a6b2b762 100644 --- a/protocol-designer/src/pages/CreateNewProtocolWizard/SelectModules.tsx +++ b/protocol-designer/src/pages/CreateNewProtocolWizard/SelectModules.tsx @@ -1,5 +1,4 @@ import { useTranslation } from 'react-i18next' -import { useSelector } from 'react-redux' import { ALIGN_CENTER, BORDERS, @@ -25,7 +24,6 @@ import { TEMPERATURE_MODULE_TYPE, } from '@opentrons/shared-data' import { uuid } from '../../utils' -import { getEnableAbsorbanceReader } from '../../feature-flags/selectors' import { useKitchen } from '../../organisms/Kitchen/hooks' import { ModuleDiagram } from './ModuleDiagram' import { WizardBody } from './WizardBody' @@ -51,7 +49,6 @@ export function SelectModules(props: WizardTileProps): JSX.Element | null { const fields = watch('fields') const modules = watch('modules') const additionalEquipment = watch('additionalEquipment') - const enableAbsorbanceReader = useSelector(getEnableAbsorbanceReader) const robotType = fields.robotType const supportedModules = robotType === FLEX_ROBOT_TYPE @@ -166,8 +163,7 @@ export function SelectModules(props: WizardTileProps): JSX.Element | null { > - {(filteredSupportedModules.length > 0 && enableAbsorbanceReader) || - // note (kk:09/26/2024) the condition for absorbanceReaderV1 will be removed when ff is removed + {filteredSupportedModules.length > 0 || !( filteredSupportedModules.length === 1 && filteredSupportedModules[0] === 'absorbanceReaderV1' @@ -179,11 +175,6 @@ export function SelectModules(props: WizardTileProps): JSX.Element | null { {filteredSupportedModules .sort((moduleA, moduleB) => moduleA.localeCompare(moduleB)) - .filter(module => - enableAbsorbanceReader - ? module - : module !== ABSORBANCE_READER_V1 - ) .map(moduleModel => { const numSlotsAvailable = getNumSlotsAvailable( modules, diff --git a/protocol-designer/src/pages/CreateNewProtocolWizard/__tests__/SelectModules.test.tsx b/protocol-designer/src/pages/CreateNewProtocolWizard/__tests__/SelectModules.test.tsx index c8c0a07cf7b..2d23f3a1fef 100644 --- a/protocol-designer/src/pages/CreateNewProtocolWizard/__tests__/SelectModules.test.tsx +++ b/protocol-designer/src/pages/CreateNewProtocolWizard/__tests__/SelectModules.test.tsx @@ -3,7 +3,6 @@ import '@testing-library/jest-dom/vitest' import { FLEX_ROBOT_TYPE, OT2_ROBOT_TYPE } from '@opentrons/shared-data' import { fireEvent, screen } from '@testing-library/react' import { i18n } from '../../../assets/localization' -import { getEnableAbsorbanceReader } from '../../../feature-flags/selectors' import { renderWithProviders } from '../../../__testing-utils__' import { SelectModules } from '../SelectModules' @@ -44,7 +43,6 @@ describe('SelectModules', () => { props = { ...mockWizardTileProps, } as WizardTileProps - vi.mocked(getEnableAbsorbanceReader).mockReturnValue(true) }) afterEach(() => { vi.restoreAllMocks() diff --git a/protocol-designer/src/pages/Designer/DeckSetup/DeckSetupTools.tsx b/protocol-designer/src/pages/Designer/DeckSetup/DeckSetupTools.tsx index 51ceab2e937..d997835e831 100644 --- a/protocol-designer/src/pages/Designer/DeckSetup/DeckSetupTools.tsx +++ b/protocol-designer/src/pages/Designer/DeckSetup/DeckSetupTools.tsx @@ -49,7 +49,6 @@ import { selectNestedLabware, selectZoomedIntoSlot, } from '../../../labware-ingred/actions' -import { getEnableAbsorbanceReader } from '../../../feature-flags/selectors' import { useBlockingHint } from '../../../organisms/BlockingHintModal/useBlockingHint' import { selectors } from '../../../labware-ingred/selectors' import { useKitchen } from '../../../organisms/Kitchen/hooks' @@ -110,7 +109,6 @@ export function DeckSetupTools(props: DeckSetupToolsProps): JSX.Element | null { 'change_magnet_module_model' ) const dispatch = useDispatch>() - const enableAbsorbanceReader = useSelector(getEnableAbsorbanceReader) const deckSetup = useSelector(getDeckSetupForActiveItem) const { selectedLabwareDefUri, @@ -144,9 +142,7 @@ export function DeckSetupTools(props: DeckSetupToolsProps): JSX.Element | null { }, [selectedModuleModel, selectedFixture]) const moduleModels = - slot != null - ? getModuleModelsBySlot(enableAbsorbanceReader, robotType, slot) - : null + slot != null ? getModuleModelsBySlot(robotType, slot) : null const [tab, setTab] = useState<'hardware' | 'labware'>( moduleModels?.length === 0 || slot === 'offDeck' ? 'labware' : 'hardware' ) diff --git a/protocol-designer/src/pages/Designer/DeckSetup/LabwareTools.tsx b/protocol-designer/src/pages/Designer/DeckSetup/LabwareTools.tsx index 0daab2f845e..df6c982a132 100644 --- a/protocol-designer/src/pages/Designer/DeckSetup/LabwareTools.tsx +++ b/protocol-designer/src/pages/Designer/DeckSetup/LabwareTools.tsx @@ -49,7 +49,6 @@ import { selectLabware, selectNestedLabware, } from '../../../labware-ingred/actions' -import { getEnableAbsorbanceReader } from '../../../feature-flags/selectors' import { ALL_ORDERED_CATEGORIES, CUSTOM_CATEGORY, @@ -134,8 +133,6 @@ export function LabwareTools(props: LabwareToolsProps): JSX.Element { robotType === OT2_ROBOT_TYPE ? isNextToHeaterShaker : false ) - const enablePlateReader = useSelector(getEnableAbsorbanceReader) - const getLabwareCompatible = useCallback( (def: LabwareDefinition2) => { // assume that custom (non-standard) labware is (potentially) compatible @@ -171,8 +168,7 @@ export function LabwareTools(props: LabwareToolsProps): JSX.Element { moduleType !== HEATERSHAKER_MODULE_TYPE) || (isAdapter96Channel && !has96Channel) || (slot === 'offDeck' && isAdapter) || - (!enablePlateReader && - PLATE_READER_LOADNAME === parameters.loadName && + (PLATE_READER_LOADNAME === parameters.loadName && moduleType !== ABSORBANCE_READER_TYPE) ) }, diff --git a/protocol-designer/src/pages/Designer/DeckSetup/__tests__/DeckSetupTools.test.tsx b/protocol-designer/src/pages/Designer/DeckSetup/__tests__/DeckSetupTools.test.tsx index 0283b9ab724..cfc366baf85 100644 --- a/protocol-designer/src/pages/Designer/DeckSetup/__tests__/DeckSetupTools.test.tsx +++ b/protocol-designer/src/pages/Designer/DeckSetup/__tests__/DeckSetupTools.test.tsx @@ -17,7 +17,6 @@ import { getSavedStepForms, } from '../../../../step-forms/selectors' import { getRobotType } from '../../../../file-data/selectors' -import { getEnableAbsorbanceReader } from '../../../../feature-flags/selectors' import { deleteDeckFixture } from '../../../../step-forms/actions/additionalItems' import { selectors } from '../../../../labware-ingred/selectors' import { getDismissedHints } from '../../../../tutorial/selectors' @@ -68,7 +67,6 @@ describe('DeckSetupTools', () => { }) vi.mocked(LabwareTools).mockReturnValue(
    mock labware tools
    ) vi.mocked(getRobotType).mockReturnValue(FLEX_ROBOT_TYPE) - vi.mocked(getEnableAbsorbanceReader).mockReturnValue(true) vi.mocked(getDeckSetupForActiveItem).mockReturnValue({ labware: {}, modules: {}, diff --git a/protocol-designer/src/pages/Designer/DeckSetup/__tests__/utils.test.ts b/protocol-designer/src/pages/Designer/DeckSetup/__tests__/utils.test.ts index 7d48c7ea71d..c2925185923 100644 --- a/protocol-designer/src/pages/Designer/DeckSetup/__tests__/utils.test.ts +++ b/protocol-designer/src/pages/Designer/DeckSetup/__tests__/utils.test.ts @@ -16,10 +16,10 @@ import { FLEX_MODULE_MODELS, OT2_MODULE_MODELS } from '../constants' describe('getModuleModelsBySlot', () => { it('renders no modules for ot-2 middle slot', () => { - expect(getModuleModelsBySlot(false, OT2_ROBOT_TYPE, '5')).toEqual([]) + expect(getModuleModelsBySlot(OT2_ROBOT_TYPE, '5')).toEqual([]) }) it('renders all ot-2 modules for slot 7', () => { - expect(getModuleModelsBySlot(false, OT2_ROBOT_TYPE, '7')).toEqual( + expect(getModuleModelsBySlot(OT2_ROBOT_TYPE, '7')).toEqual( OT2_MODULE_MODELS ) }) @@ -28,7 +28,7 @@ describe('getModuleModelsBySlot', () => { model => model !== THERMOCYCLER_MODULE_V1 && model !== THERMOCYCLER_MODULE_V2 ) - expect(getModuleModelsBySlot(false, OT2_ROBOT_TYPE, '1')).toEqual(noTC) + expect(getModuleModelsBySlot(OT2_ROBOT_TYPE, '1')).toEqual(noTC) }) it('renders ot-2 modules minus thermocyclers & heater-shaker for slot 9', () => { const noTCAndHS = OT2_MODULE_MODELS.filter( @@ -37,15 +37,15 @@ describe('getModuleModelsBySlot', () => { model !== THERMOCYCLER_MODULE_V2 && model !== HEATERSHAKER_MODULE_V1 ) - expect(getModuleModelsBySlot(false, OT2_ROBOT_TYPE, '9')).toEqual(noTCAndHS) + expect(getModuleModelsBySlot(OT2_ROBOT_TYPE, '9')).toEqual(noTCAndHS) }) it('renders flex modules for middle slots', () => { - expect(getModuleModelsBySlot(false, FLEX_ROBOT_TYPE, 'B2')).toEqual([ + expect(getModuleModelsBySlot(FLEX_ROBOT_TYPE, 'B2')).toEqual([ MAGNETIC_BLOCK_V1, ]) }) it('renders all flex modules for B1', () => { - expect(getModuleModelsBySlot(true, FLEX_ROBOT_TYPE, 'B1')).toEqual( + expect(getModuleModelsBySlot(FLEX_ROBOT_TYPE, 'B1')).toEqual( FLEX_MODULE_MODELS.filter(model => model !== ABSORBANCE_READER_V1) ) }) @@ -54,7 +54,7 @@ describe('getModuleModelsBySlot', () => { model => model !== THERMOCYCLER_MODULE_V2 && model !== ABSORBANCE_READER_V1 ) - expect(getModuleModelsBySlot(true, FLEX_ROBOT_TYPE, 'C1')).toEqual(noTC) + expect(getModuleModelsBySlot(FLEX_ROBOT_TYPE, 'C1')).toEqual(noTC) }) }) diff --git a/protocol-designer/src/pages/Designer/DeckSetup/utils.ts b/protocol-designer/src/pages/Designer/DeckSetup/utils.ts index 0b1a455f3d4..1da3609df68 100644 --- a/protocol-designer/src/pages/Designer/DeckSetup/utils.ts +++ b/protocol-designer/src/pages/Designer/DeckSetup/utils.ts @@ -61,7 +61,6 @@ export function getCutoutIdForAddressableArea( } export function getModuleModelsBySlot( - enableAbsorbanceReader: boolean, robotType: RobotType, slot: DeckSlotId ): ModuleModelExtended[] { @@ -88,7 +87,7 @@ export function getModuleModelsBySlot( if (model === THERMOCYCLER_MODULE_V2) { return slot === 'B1' } else if (model === ABSORBANCE_READER_V1) { - return FLEX_RIGHT_SLOTS.has(slot) && enableAbsorbanceReader + return FLEX_RIGHT_SLOTS.has(slot) } else if ( model === TEMPERATURE_MODULE_V2 || model === HEATERSHAKER_MODULE_V1 diff --git a/protocol-designer/src/pages/Designer/ProtocolSteps/Timeline/AddStepButton.tsx b/protocol-designer/src/pages/Designer/ProtocolSteps/Timeline/AddStepButton.tsx index 52460aee461..16d7add611e 100644 --- a/protocol-designer/src/pages/Designer/ProtocolSteps/Timeline/AddStepButton.tsx +++ b/protocol-designer/src/pages/Designer/ProtocolSteps/Timeline/AddStepButton.tsx @@ -45,10 +45,7 @@ import { ConfirmDeleteModal, getMainPagePortalEl, } from '../../../../organisms' -import { - getEnableAbsorbanceReader, - getEnableComment, -} from '../../../../feature-flags/selectors' +import { getEnableComment } from '../../../../feature-flags/selectors' import { AddStepOverflowButton } from './AddStepOverflowButton' import type { MouseEvent } from 'react' @@ -87,7 +84,6 @@ export function AddStepButton({ hasText }: AddStepButtonProps): JSX.Element { const [enqueuedStepType, setEnqueuedStepType] = useState( null ) - const enableAbsorbanceReader = useSelector(getEnableAbsorbanceReader) const getSupportedSteps = (): Array< Exclude @@ -116,9 +112,7 @@ export function AddStepButton({ hasText }: AddStepButtonProps): JSX.Element { temperature: getIsModuleOnDeck(modules, TEMPERATURE_MODULE_TYPE), thermocycler: getIsModuleOnDeck(modules, THERMOCYCLER_MODULE_TYPE), heaterShaker: getIsModuleOnDeck(modules, HEATERSHAKER_MODULE_TYPE), - absorbanceReader: - getIsModuleOnDeck(modules, ABSORBANCE_READER_TYPE) && - enableAbsorbanceReader, + absorbanceReader: getIsModuleOnDeck(modules, ABSORBANCE_READER_TYPE), } const addStep = (stepType: StepType): ReturnType => diff --git a/protocol-designer/src/step-forms/selectors/index.ts b/protocol-designer/src/step-forms/selectors/index.ts index 3dcac3bd735..160410217e4 100644 --- a/protocol-designer/src/step-forms/selectors/index.ts +++ b/protocol-designer/src/step-forms/selectors/index.ts @@ -675,15 +675,13 @@ export const getInvariantContext: Selector< getAdditionalEquipmentEntities, featureFlagSelectors.getDisableModuleRestrictions, featureFlagSelectors.getAllowAllTipracks, - featureFlagSelectors.getEnableAbsorbanceReader, ( labwareEntities, moduleEntities, pipetteEntities, additionalEquipmentEntities, disableModuleRestrictions, - allowAllTipracks, - enableAbsorbanceReader + allowAllTipracks ) => ({ labwareEntities, moduleEntities, @@ -692,7 +690,6 @@ export const getInvariantContext: Selector< config: { OT_PD_ALLOW_ALL_TIPRACKS: Boolean(allowAllTipracks), OT_PD_DISABLE_MODULE_RESTRICTIONS: Boolean(disableModuleRestrictions), - OT_PD_ENABLE_ABSORBANCE_READER: Boolean(enableAbsorbanceReader), }, }) ) From 13a1c856f335f9fc97c082713564677f88a9efe2 Mon Sep 17 00:00:00 2001 From: Ryan Howard Date: Tue, 28 Jan 2025 17:14:20 -0500 Subject: [PATCH 12/22] fix(shared-data): Fixup some values for the new pipette (#17371) # Overview Some of the values that were hardcoded in hardware-testing did not make it into the shared data definitions during tuning at the factory. This corrects all of that ## Test Plan and Hands on Testing ## Changelog ## Review requests ## Risk assessment --- .../eight_channel/p1000/default/3_5.json | 2 +- .../ninety_six_channel/p200/default/3_0.json | 38 +++++++++---------- .../single_channel/p1000/default/3_5.json | 2 +- .../single_channel/p1000/default/3_6.json | 2 +- .../single_channel/p1000/default/3_7.json | 2 +- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/shared-data/pipette/definitions/2/liquid/eight_channel/p1000/default/3_5.json b/shared-data/pipette/definitions/2/liquid/eight_channel/p1000/default/3_5.json index 1b734fe1011..09401af422d 100644 --- a/shared-data/pipette/definitions/2/liquid/eight_channel/p1000/default/3_5.json +++ b/shared-data/pipette/definitions/2/liquid/eight_channel/p1000/default/3_5.json @@ -15,7 +15,7 @@ "default": 57, "valuesByApiLevel": { "2.14": 57 } }, - "defaultFlowAcceleration": 1200.0, + "defaultFlowAcceleration": 24000.0, "defaultTipLength": 52.0, "defaultReturnTipHeight": 0.71, "aspirate": { diff --git a/shared-data/pipette/definitions/2/liquid/ninety_six_channel/p200/default/3_0.json b/shared-data/pipette/definitions/2/liquid/ninety_six_channel/p200/default/3_0.json index d2814dca3c1..42963f4e7ff 100644 --- a/shared-data/pipette/definitions/2/liquid/ninety_six_channel/p200/default/3_0.json +++ b/shared-data/pipette/definitions/2/liquid/ninety_six_channel/p200/default/3_0.json @@ -2,20 +2,20 @@ "$otSharedSchema": "#/pipette/schemas/2/pipetteLiquidPropertiesSchema.json", "supportedTips": { "t20": { - "uiMaxFlowRate": 189.1, + "uiMaxFlowRate": 45, "defaultAspirateFlowRate": { - "default": 6, - "valuesByApiLevel": { "2.14": 6 } + "default": 6.5, + "valuesByApiLevel": { "2.14": 6.5 } }, "defaultDispenseFlowRate": { - "default": 6, - "valuesByApiLevel": { "2.14": 6 } + "default": 6.5, + "valuesByApiLevel": { "2.14": 6.5 } }, "defaultBlowOutFlowRate": { "default": 10, "valuesByApiLevel": { "2.14": 10 } }, - "defaultFlowAcceleration": 16000.0, + "defaultFlowAcceleration": 3160.0, "defaultTipLength": 52.0, "defaultReturnTipHeight": 0.6, "aspirate": { @@ -51,20 +51,20 @@ "defaultPushOutVolume": 2 }, "t50": { - "uiMaxFlowRate": 194, + "uiMaxFlowRate": 45, "defaultAspirateFlowRate": { - "default": 6, - "valuesByApiLevel": { "2.14": 6 } + "default": 6.5, + "valuesByApiLevel": { "2.14": 6.5 } }, "defaultDispenseFlowRate": { - "default": 6, - "valuesByApiLevel": { "2.14": 6 } + "default": 6.5, + "valuesByApiLevel": { "2.14": 6.5 } }, "defaultBlowOutFlowRate": { "default": 10, "valuesByApiLevel": { "2.14": 10 } }, - "defaultFlowAcceleration": 16000.0, + "defaultFlowAcceleration": 3160.0, "defaultTipLength": 57.9, "defaultReturnTipHeight": 0.2, "aspirate": { @@ -114,20 +114,20 @@ "defaultPushOutVolume": 7 }, "t200": { - "uiMaxFlowRate": 194, + "uiMaxFlowRate": 45, "defaultAspirateFlowRate": { - "default": 80, - "valuesByApiLevel": { "2.14": 80 } + "default": 15, + "valuesByApiLevel": { "2.14": 15 } }, "defaultDispenseFlowRate": { - "default": 80, - "valuesByApiLevel": { "2.14": 80 } + "default": 15, + "valuesByApiLevel": { "2.14": 15 } }, "defaultBlowOutFlowRate": { "default": 10, "valuesByApiLevel": { "2.14": 10 } }, - "defaultFlowAcceleration": 16000.0, + "defaultFlowAcceleration": 3160.0, "defaultTipLength": 58.35, "defaultReturnTipHeight": 0.2, "aspirate": { @@ -170,7 +170,7 @@ } }, "maxVolume": 200, - "minVolume": 1, + "minVolume": 0.5, "defaultTipracks": [ "opentrons/opentrons_flex_96_tiprack_200ul/1", "opentrons/opentrons_flex_96_tiprack_50ul/1", diff --git a/shared-data/pipette/definitions/2/liquid/single_channel/p1000/default/3_5.json b/shared-data/pipette/definitions/2/liquid/single_channel/p1000/default/3_5.json index c70853beff3..9e126f536f5 100644 --- a/shared-data/pipette/definitions/2/liquid/single_channel/p1000/default/3_5.json +++ b/shared-data/pipette/definitions/2/liquid/single_channel/p1000/default/3_5.json @@ -15,7 +15,7 @@ "default": 57, "valuesByApiLevel": { "2.14": 57 } }, - "defaultFlowAcceleration": 1200.0, + "defaultFlowAcceleration": 24000.0, "defaultTipLength": 52.0, "defaultReturnTipHeight": 0.71, "aspirate": { diff --git a/shared-data/pipette/definitions/2/liquid/single_channel/p1000/default/3_6.json b/shared-data/pipette/definitions/2/liquid/single_channel/p1000/default/3_6.json index c8c3a02b398..6b902337a7d 100644 --- a/shared-data/pipette/definitions/2/liquid/single_channel/p1000/default/3_6.json +++ b/shared-data/pipette/definitions/2/liquid/single_channel/p1000/default/3_6.json @@ -15,7 +15,7 @@ "default": 57, "valuesByApiLevel": { "2.14": 57 } }, - "defaultFlowAcceleration": 1200.0, + "defaultFlowAcceleration": 24000.0, "defaultTipLength": 52.0, "defaultReturnTipHeight": 0.71, "aspirate": { diff --git a/shared-data/pipette/definitions/2/liquid/single_channel/p1000/default/3_7.json b/shared-data/pipette/definitions/2/liquid/single_channel/p1000/default/3_7.json index c8c3a02b398..3822d30c2f4 100644 --- a/shared-data/pipette/definitions/2/liquid/single_channel/p1000/default/3_7.json +++ b/shared-data/pipette/definitions/2/liquid/single_channel/p1000/default/3_7.json @@ -15,7 +15,7 @@ "default": 57, "valuesByApiLevel": { "2.14": 57 } }, - "defaultFlowAcceleration": 1200.0, + "defaultFlowAcceleration": 2400.0, "defaultTipLength": 52.0, "defaultReturnTipHeight": 0.71, "aspirate": { From 5b917271a38581cc2ffe216bd3b906fb0d0caa1e Mon Sep 17 00:00:00 2001 From: Brayan Almonte Date: Wed, 29 Jan 2025 09:00:59 -0500 Subject: [PATCH 13/22] fix(api,shared-data): FlexStacker fixes and improvements to enable ABR/Science. (#17350) - Increased flex stacker z current from 1.5mA to 1.8mA to account for full tipracks - Increased the offset used when moving the z axis for storing tall labware like tipracks - added await get_motion_params call when initializing the move_params in the FlexStacker module. - added lid height if lid is used in the retrieve.py and store.py commands. - exclude lids on top of tipracks in the Flex Stacker when getting the highest z. - add flexStackerModuleV1D4 addressable area to the flex stacker + waste chute fixture - adjust the `stackingOffsetWithLabware` z from 8.193 to 14 for `opentrons_flex_tiprack_lid` - increase the `gripHeightFromLabwareTop` from 8 to 10 for `opentrons_flex_tiprack_lid` - decrease the `gripForce` from 15 to 10 for `opentrons_flex_tiprack_lid` --- .../opentrons/drivers/flex_stacker/driver.py | 12 +++---- .../hardware_control/modules/flex_stacker.py | 8 +++-- .../commands/flex_stacker/retrieve.py | 13 ++++--- .../commands/flex_stacker/store.py | 11 ++++-- .../protocol_engine/state/geometry.py | 1 + .../commands/flex_stacker/test_retrieve.py | 34 +++++++++++++++++-- .../commands/flex_stacker/test_store.py | 34 +++++++++++++++++-- .../opentrons/protocol_engine/conftest.py | 8 +++++ .../deck/definitions/5/ot3_standard.json | 6 +++- .../3/opentrons_flex_tiprack_lid/1.json | 18 +++++----- .../opentrons_shared_data/labware/__init__.py | 6 ++-- 11 files changed, 119 insertions(+), 32 deletions(-) diff --git a/api/src/opentrons/drivers/flex_stacker/driver.py b/api/src/opentrons/drivers/flex_stacker/driver.py index 366ea08b5f5..449233d1dee 100644 --- a/api/src/opentrons/drivers/flex_stacker/driver.py +++ b/api/src/opentrons/drivers/flex_stacker/driver.py @@ -33,10 +33,10 @@ StackerAxis.X: { "home": MoveParams( StackerAxis.X, - max_speed=10.0, - acceleration=100.0, - max_speed_discont=40, - current=1.5, + max_speed=10.0, # mm/s + acceleration=100.0, # mm/s^2 + max_speed_discont=40, # mm/s + current=1.5, # mAmps ), "move": MoveParams( StackerAxis.X, @@ -52,14 +52,14 @@ max_speed=10.0, acceleration=100.0, max_speed_discont=40, - current=1.5, + current=1.8, ), "move": MoveParams( StackerAxis.Z, max_speed=200.0, acceleration=500.0, max_speed_discont=40, - current=1.5, + current=1.8, ), }, StackerAxis.L: { diff --git a/api/src/opentrons/hardware_control/modules/flex_stacker.py b/api/src/opentrons/hardware_control/modules/flex_stacker.py index 295311e05ca..686653a2f24 100644 --- a/api/src/opentrons/hardware_control/modules/flex_stacker.py +++ b/api/src/opentrons/hardware_control/modules/flex_stacker.py @@ -55,6 +55,9 @@ OFFSET_MD = 10.0 OFFSET_LG = 20.0 +# height limit in mm of labware to use OFFSET_MD used when storing labware. +MEDIUM_LABWARE_Z_LIMIT = 20.0 + class FlexStacker(mod_abc.AbstractModule): """Hardware control interface for an attached Flex-Stacker module.""" @@ -344,7 +347,8 @@ async def store_labware(self, labware_height: float) -> bool: await self._prepare_for_action() # Move X then Z axis - distance = MAX_TRAVEL[StackerAxis.Z] - (labware_height / 2) - OFFSET_MD + offset = OFFSET_MD if labware_height < MEDIUM_LABWARE_Z_LIMIT else OFFSET_LG * 2 + distance = MAX_TRAVEL[StackerAxis.Z] - (labware_height / 2) - offset await self._move_and_home_axis(StackerAxis.X, Direction.RETRACT, OFFSET_SM) await self.move_axis(StackerAxis.Z, Direction.EXTENT, distance) @@ -410,7 +414,7 @@ async def get_limit_switch_status(self) -> None: async def get_motion_parameters(self) -> None: """Get the motion parameters used by the axis motors.""" self.move_params = { - axis: self._driver.get_motion_params(axis) for axis in StackerAxis + axis: await self._driver.get_motion_params(axis) for axis in StackerAxis } async def get_platform_sensor_state(self) -> None: diff --git a/api/src/opentrons/protocol_engine/commands/flex_stacker/retrieve.py b/api/src/opentrons/protocol_engine/commands/flex_stacker/retrieve.py index 6b932322c0d..7029b5772c3 100644 --- a/api/src/opentrons/protocol_engine/commands/flex_stacker/retrieve.py +++ b/api/src/opentrons/protocol_engine/commands/flex_stacker/retrieve.py @@ -83,11 +83,16 @@ async def execute(self, params: RetrieveParams) -> SuccessData[RetrieveResult]: # Get the labware dimensions for the labware being retrieved, # which is the first one in the hopper labware id list lw_id = stacker_state.hopper_labware_ids[0] - lw_dim = self._state_view.labware.get_dimensions(labware_id=lw_id) - if stacker_hw is not None: - # Dispense the labware from the Flex Stacker using the labware height - await stacker_hw.dispense_labware(labware_height=lw_dim.z) + labware = self._state_view.labware.get(lw_id) + labware_height = self._state_view.labware.get_dimensions(labware_id=lw_id).z + if labware.lid_id is not None: + lid_def = self._state_view.labware.get_definition(labware.lid_id) + offset = self._state_view.labware.get_labware_overlap_offsets( + lid_def, labware.loadName + ).z + labware_height = labware_height + lid_def.dimensions.zDimension - offset + await stacker_hw.dispense_labware(labware_height=labware_height) # update the state to reflect the labware is now in the flex stacker slot state_update.set_labware_location( diff --git a/api/src/opentrons/protocol_engine/commands/flex_stacker/store.py b/api/src/opentrons/protocol_engine/commands/flex_stacker/store.py index 206c8ee59a9..37f2d9f7616 100644 --- a/api/src/opentrons/protocol_engine/commands/flex_stacker/store.py +++ b/api/src/opentrons/protocol_engine/commands/flex_stacker/store.py @@ -68,12 +68,19 @@ async def execute(self, params: StoreParams) -> SuccessData[StoreResult]: "Cannot store labware if Flex Stacker carriage is empty" ) - lw_dim = self._state_view.labware.get_dimensions(labware_id=lw_id) # TODO: check the type of the labware should match that already in the stack state_update = update_types.StateUpdate() if stacker_hw is not None: - await stacker_hw.store_labware(labware_height=lw_dim.z) + labware = self._state_view.labware.get(lw_id) + labware_height = self._state_view.labware.get_dimensions(labware_id=lw_id).z + if labware.lid_id is not None: + lid_def = self._state_view.labware.get_definition(labware.lid_id) + offset = self._state_view.labware.get_labware_overlap_offsets( + lid_def, labware.loadName + ).z + labware_height = labware_height + lid_def.dimensions.zDimension - offset + await stacker_hw.store_labware(labware_height=labware_height) # update the state to reflect the labware is store in the stack state_update.set_labware_location( diff --git a/api/src/opentrons/protocol_engine/state/geometry.py b/api/src/opentrons/protocol_engine/state/geometry.py index 0344ef321fc..cf6b4521713 100644 --- a/api/src/opentrons/protocol_engine/state/geometry.py +++ b/api/src/opentrons/protocol_engine/state/geometry.py @@ -161,6 +161,7 @@ def get_all_obstacle_highest_z(self) -> float: self._get_highest_z_from_labware_data(lw_data) for lw_data in self._labware.get_all() if lw_data.location != OFF_DECK_LOCATION + and not self._labware.get_labware_by_lid_id(lw_data.id) ), default=0.0, ) diff --git a/api/tests/opentrons/protocol_engine/commands/flex_stacker/test_retrieve.py b/api/tests/opentrons/protocol_engine/commands/flex_stacker/test_retrieve.py index 533f99ce2fd..6f11b2908b7 100644 --- a/api/tests/opentrons/protocol_engine/commands/flex_stacker/test_retrieve.py +++ b/api/tests/opentrons/protocol_engine/commands/flex_stacker/test_retrieve.py @@ -1,9 +1,10 @@ """Test Flex Stacker retrieve command implementation.""" -from decoy import Decoy import pytest +from decoy import Decoy from contextlib import nullcontext as does_not_raise from typing import ContextManager, Any +from opentrons.calibration_storage.helpers import uri_from_details from opentrons.hardware_control.modules import FlexStacker from opentrons.protocol_engine.state.state import StateView @@ -21,8 +22,17 @@ from opentrons.protocol_engine.commands import flex_stacker from opentrons.protocol_engine.commands.command import SuccessData from opentrons.protocol_engine.commands.flex_stacker.retrieve import RetrieveImpl -from opentrons.protocol_engine.types import Dimensions, ModuleLocation +from opentrons.protocol_engine.types import ( + DeckSlotLocation, + Dimensions, + ModuleLocation, + LoadedLabware, + OverlapOffset, +) from opentrons.protocol_engine.errors import CannotPerformModuleAction +from opentrons.types import DeckSlotName + +from opentrons_shared_data.labware.labware_definition import LabwareDefinition @pytest.mark.parametrize( @@ -44,6 +54,7 @@ async def test_retrieve( equipment: EquipmentHandler, in_static_mode: bool, expectation: ContextManager[Any], + tiprack_lid_def: LabwareDefinition, ) -> None: """It should be able to retrieve a labware.""" subject = RetrieveImpl(state_view=state_view, equipment=equipment) @@ -59,11 +70,28 @@ async def test_retrieve( decoy.when( state_view.modules.get_flex_stacker_substate(module_id="flex-stacker-id") ).then_return(fs_module_substate) + decoy.when(state_view.labware.get("labware-id")).then_return( + LoadedLabware( + id="labware-id", + loadName="tiprack", + definitionUri=uri_from_details(namespace="a", load_name="b", version=1), + location=DeckSlotLocation(slotName=DeckSlotName.SLOT_3), + offsetId=None, + lid_id="lid-id", + displayName="Labware", + ) + ) decoy.when(state_view.labware.get_dimensions(labware_id="labware-id")).then_return( Dimensions(x=1, y=1, z=1) ) + decoy.when(state_view.labware.get_definition("lid-id")).then_return(tiprack_lid_def) + + decoy.when( + state_view.labware.get_labware_overlap_offsets(tiprack_lid_def, "tiprack") + ).then_return(OverlapOffset(x=0, y=0, z=14)) + decoy.when( equipment.get_module_hardware_api(FlexStackerId("flex-stacker-id")) ).then_return(fs_hardware) @@ -72,7 +100,7 @@ async def test_retrieve( result = await subject.execute(data) if not in_static_mode: - decoy.verify(await fs_hardware.dispense_labware(labware_height=1), times=1) + decoy.verify(await fs_hardware.dispense_labware(labware_height=4), times=1) assert result == SuccessData( public=flex_stacker.RetrieveResult(labware_id="labware-id"), diff --git a/api/tests/opentrons/protocol_engine/commands/flex_stacker/test_store.py b/api/tests/opentrons/protocol_engine/commands/flex_stacker/test_store.py index f7eaf9b4eb9..1d6ea1b9947 100644 --- a/api/tests/opentrons/protocol_engine/commands/flex_stacker/test_store.py +++ b/api/tests/opentrons/protocol_engine/commands/flex_stacker/test_store.py @@ -1,9 +1,10 @@ """Test Flex Stacker store command implementation.""" -from decoy import Decoy import pytest +from decoy import Decoy from contextlib import nullcontext as does_not_raise from typing import ContextManager, Any +from opentrons.calibration_storage.helpers import uri_from_details from opentrons.hardware_control.modules import FlexStacker from opentrons.protocol_engine.state.update_types import ( @@ -22,8 +23,17 @@ from opentrons.protocol_engine.commands import flex_stacker from opentrons.protocol_engine.commands.command import SuccessData from opentrons.protocol_engine.commands.flex_stacker.store import StoreImpl -from opentrons.protocol_engine.types import Dimensions, OFF_DECK_LOCATION +from opentrons.protocol_engine.types import ( + DeckSlotLocation, + Dimensions, + OFF_DECK_LOCATION, + LoadedLabware, + OverlapOffset, +) from opentrons.protocol_engine.errors import CannotPerformModuleAction +from opentrons.types import DeckSlotName + +from opentrons_shared_data.labware.labware_definition import LabwareDefinition @pytest.mark.parametrize( @@ -45,6 +55,7 @@ async def test_store( equipment: EquipmentHandler, in_static_mode: bool, expectation: ContextManager[Any], + tiprack_lid_def: LabwareDefinition, ) -> None: """It should be able to store a labware.""" subject = StoreImpl(state_view=state_view, equipment=equipment) @@ -64,11 +75,28 @@ async def test_store( decoy.when( state_view.labware.get_id_by_module(module_id="flex-stacker-id") ).then_return("labware-id") + decoy.when(state_view.labware.get("labware-id")).then_return( + LoadedLabware( + id="labware-id", + loadName="tiprack", + definitionUri=uri_from_details(namespace="a", load_name="b", version=1), + location=DeckSlotLocation(slotName=DeckSlotName.SLOT_3), + offsetId=None, + lid_id="lid-id", + displayName="Labware", + ) + ) decoy.when(state_view.labware.get_dimensions(labware_id="labware-id")).then_return( Dimensions(x=1, y=1, z=1) ) + decoy.when(state_view.labware.get_definition("lid-id")).then_return(tiprack_lid_def) + + decoy.when( + state_view.labware.get_labware_overlap_offsets(tiprack_lid_def, "tiprack") + ).then_return(OverlapOffset(x=0, y=0, z=14)) + decoy.when( equipment.get_module_hardware_api(FlexStackerId("flex-stacker-id")) ).then_return(fs_hardware) @@ -77,7 +105,7 @@ async def test_store( result = await subject.execute(data) if not in_static_mode: - decoy.verify(await fs_hardware.store_labware(labware_height=1), times=1) + decoy.verify(await fs_hardware.store_labware(labware_height=4), times=1) assert result == SuccessData( public=flex_stacker.StoreResult(), state_update=StateUpdate( diff --git a/api/tests/opentrons/protocol_engine/conftest.py b/api/tests/opentrons/protocol_engine/conftest.py index acc7d2e8829..c09d082afa2 100644 --- a/api/tests/opentrons/protocol_engine/conftest.py +++ b/api/tests/opentrons/protocol_engine/conftest.py @@ -171,6 +171,14 @@ def magdeck_well_plate_def() -> LabwareDefinition: ) +@pytest.fixture(scope="session") +def tiprack_lid_def() -> LabwareDefinition: + """Get the definition of the opentrons tiprack lid.""" + return LabwareDefinition.model_validate( + load_definition("opentrons_flex_tiprack_lid", 1, schema=3) + ) + + @pytest.fixture(scope="session") def tempdeck_v1_def() -> ModuleDefinition: """Get the definition of a V1 tempdeck.""" diff --git a/shared-data/deck/definitions/5/ot3_standard.json b/shared-data/deck/definitions/5/ot3_standard.json index 9358c5844d0..fda49c38f2d 100644 --- a/shared-data/deck/definitions/5/ot3_standard.json +++ b/shared-data/deck/definitions/5/ot3_standard.json @@ -1023,7 +1023,11 @@ "mayMountTo": ["cutoutD3"], "displayName": "Flex Stacker With Waste Chute Adapter for 96 Channel Pipette or Gripper", "providesAddressableAreas": { - "cutoutD3": ["1ChannelWasteChute", "8ChannelWasteChute", "D4"] + "cutoutD3": [ + "1ChannelWasteChute", + "8ChannelWasteChute", + "flexStackerModuleV1D4" + ] }, "fixtureGroup": {}, "height": 124.5 diff --git a/shared-data/labware/definitions/3/opentrons_flex_tiprack_lid/1.json b/shared-data/labware/definitions/3/opentrons_flex_tiprack_lid/1.json index 9b5197e143d..88e3b604921 100644 --- a/shared-data/labware/definitions/3/opentrons_flex_tiprack_lid/1.json +++ b/shared-data/labware/definitions/3/opentrons_flex_tiprack_lid/1.json @@ -43,37 +43,37 @@ "default": { "x": 0, "y": 0, - "z": 8.193 + "z": 14 }, "opentrons_flex_96_filtertiprack_200ul": { "x": 0, "y": 0, - "z": 8.25 + "z": 14 }, "opentrons_flex_96_filtertiprack_1000ul": { "x": 0, "y": 0, - "z": 8.25 + "z": 14 }, "opentrons_flex_96_tiprack_20ul": { "x": 0, "y": 0, - "z": 8.25 + "z": 14 }, "opentrons_flex_96_tiprack_50ul": { "x": 0, "y": 0, - "z": 8.25 + "z": 14 }, "opentrons_flex_96_tiprack_200ul": { "x": 0, "y": 0, - "z": 8.25 + "z": 14 }, "opentrons_flex_96_tiprack_1000ul": { "x": 0, "y": 0, - "z": 8.25 + "z": 14 } }, "stackLimit": 1, @@ -85,8 +85,8 @@ "opentrons_flex_96_filertiprack_200ul", "opentrons_flex_96_filertiprack_1000ul" ], - "gripForce": 15, - "gripHeightFromLabwareBottom": 8, + "gripForce": 10, + "gripHeightFromLabwareBottom": 10, "gripperOffsets": { "default": { "pickUpOffset": { diff --git a/shared-data/python/opentrons_shared_data/labware/__init__.py b/shared-data/python/opentrons_shared_data/labware/__init__.py index 8ffd7cbdf55..1a9fa1c2800 100644 --- a/shared-data/python/opentrons_shared_data/labware/__init__.py +++ b/shared-data/python/opentrons_shared_data/labware/__init__.py @@ -12,9 +12,11 @@ Schema = NewType("Schema", Dict[str, Any]) -def load_definition(loadname: str, version: int) -> "LabwareDefinition": +def load_definition( + loadname: str, version: int, schema: int = 2 +) -> "LabwareDefinition": return json.loads( - load_shared_data(f"labware/definitions/2/{loadname}/{version}.json") + load_shared_data(f"labware/definitions/{schema}/{loadname}/{version}.json") ) From fd2533dcb6fd493b82059b14a175c3d9dd4337a4 Mon Sep 17 00:00:00 2001 From: Brayan Almonte Date: Wed, 29 Jan 2025 09:18:37 -0500 Subject: [PATCH 14/22] feat(api): Add FlexStacker functionality to enable stallguard + add animation patterns to set_led . (#17349) - added set_motor_stallguard_threshold (M910) command) - added get_motor_stallguard_threshold (M911) command - added get_motor_driver_register (M920) command - added set_motor_driver_register (M921) command - added parse reset reason to the get_device_info command - fixed issue where driver.get_motion_params was not awaited on the FlexStacker module - rename Direction.EXTENT to Direction.EXTEND - validate the serial number before setting it. - add `set_led_state` to the FlexStacker module - added handling for motors stall errors (ERR403) - catch MotorStall exception in flex stacker driver to set MoveResult.STALL_ERROR - fixed an issue with set_led not setting the K arg properly - handle MoveResult.STALL_ERROR and raise FlexStackerStallError in `home_axis` and `move_axis` - set DEFAULT_FS_TIMEOUT to 1 second and added FS_MOVE_TIMEOUT 20s - clear serial input/output buffers if there is an error --- .../asyncio/communication/async_serial.py | 4 + .../drivers/asyncio/communication/errors.py | 7 + .../communication/serial_connection.py | 12 +- .../drivers/flex_stacker/__init__.py | 3 +- .../drivers/flex_stacker/abstract.py | 40 +++- .../opentrons/drivers/flex_stacker/driver.py | 180 +++++++++++++++--- .../drivers/flex_stacker/simulator.py | 61 +++++- .../opentrons/drivers/flex_stacker/types.py | 37 +++- .../hardware_control/modules/errors.py | 9 + .../hardware_control/modules/flex_stacker.py | 66 +++++-- .../drivers/flex_stacker/test_driver.py | 129 +++++++++++-- 11 files changed, 475 insertions(+), 73 deletions(-) diff --git a/api/src/opentrons/drivers/asyncio/communication/async_serial.py b/api/src/opentrons/drivers/asyncio/communication/async_serial.py index 8d2db0ddda7..4d0404b9eb0 100644 --- a/api/src/opentrons/drivers/asyncio/communication/async_serial.py +++ b/api/src/opentrons/drivers/asyncio/communication/async_serial.py @@ -155,6 +155,10 @@ def reset_input_buffer(self) -> None: """Reset the input buffer""" self._serial.reset_input_buffer() + def reset_output_buffer(self) -> None: + """Reset the output buffer""" + self._serial.reset_output_buffer() + @contextlib.asynccontextmanager async def timeout_override( self, timeout_property: TimeoutProperties, timeout: Optional[float] diff --git a/api/src/opentrons/drivers/asyncio/communication/errors.py b/api/src/opentrons/drivers/asyncio/communication/errors.py index 48f66356319..b48353e1ff6 100644 --- a/api/src/opentrons/drivers/asyncio/communication/errors.py +++ b/api/src/opentrons/drivers/asyncio/communication/errors.py @@ -6,6 +6,7 @@ class ErrorCodes(Enum): UNHANDLED_GCODE = "ERR003" + MOTOR_STALL = "ERR403" class SerialException(Exception): @@ -43,3 +44,9 @@ class UnhandledGcode(ErrorResponse): def __init__(self, port: str, response: str, command: str) -> None: self.command = command super().__init__(port, response) + + +class MotorStall(ErrorResponse): + def __init__(self, port: str, response: str, command: str) -> None: + self.command = command + super().__init__(port, response) diff --git a/api/src/opentrons/drivers/asyncio/communication/serial_connection.py b/api/src/opentrons/drivers/asyncio/communication/serial_connection.py index f925cfe8680..c7e3588e25a 100644 --- a/api/src/opentrons/drivers/asyncio/communication/serial_connection.py +++ b/api/src/opentrons/drivers/asyncio/communication/serial_connection.py @@ -6,7 +6,14 @@ from opentrons.drivers.command_builder import CommandBuilder -from .errors import NoResponse, AlarmResponse, ErrorResponse, UnhandledGcode, ErrorCodes +from .errors import ( + MotorStall, + NoResponse, + AlarmResponse, + ErrorResponse, + UnhandledGcode, + ErrorCodes, +) from .async_serial import AsyncSerial log = logging.getLogger(__name__) @@ -254,6 +261,9 @@ def raise_on_error(self, response: str, request: str) -> None: raise UnhandledGcode( port=self._port, response=response, command=request ) + + elif ErrorCodes.MOTOR_STALL.value.lower() in lower: + raise MotorStall(port=self._port, response=response, command=request) else: raise ErrorResponse(port=self._port, response=response) diff --git a/api/src/opentrons/drivers/flex_stacker/__init__.py b/api/src/opentrons/drivers/flex_stacker/__init__.py index 66b4cda546b..1fe2c22b43e 100644 --- a/api/src/opentrons/drivers/flex_stacker/__init__.py +++ b/api/src/opentrons/drivers/flex_stacker/__init__.py @@ -1,5 +1,5 @@ from .abstract import AbstractFlexStackerDriver -from .driver import FlexStackerDriver, STACKER_MOTION_CONFIG +from .driver import FlexStackerDriver, STACKER_MOTION_CONFIG, STALLGUARD_CONFIG from .simulator import SimulatingDriver from . import types as FlexStackerTypes @@ -9,4 +9,5 @@ "SimulatingDriver", "FlexStackerTypes", "STACKER_MOTION_CONFIG", + "STALLGUARD_CONFIG", ] diff --git a/api/src/opentrons/drivers/flex_stacker/abstract.py b/api/src/opentrons/drivers/flex_stacker/abstract.py index 222e6715086..9af5c78859a 100644 --- a/api/src/opentrons/drivers/flex_stacker/abstract.py +++ b/api/src/opentrons/drivers/flex_stacker/abstract.py @@ -1,6 +1,7 @@ -from typing import List, Protocol +from typing import List, Optional, Protocol from .types import ( + LEDPattern, LimitSwitchStatus, MoveResult, StackerAxis, @@ -9,6 +10,7 @@ MoveParams, StackerInfo, LEDColor, + StallGuardParams, ) @@ -51,10 +53,30 @@ async def set_ihold_current(self, axis: StackerAxis, current: float) -> bool: """Set axis hold current in amps.""" ... + async def set_stallguard_threshold( + self, axis: StackerAxis, enable: bool, threshold: int + ) -> bool: + """Enables and sets the stallguard threshold for the given axis motor.""" + ... + + async def set_motor_driver_register( + self, axis: StackerAxis, reg: int, value: int + ) -> bool: + """Set the register of the given motor axis driver to the given value.""" + ... + + async def get_motor_driver_register(self, axis: StackerAxis, reg: int) -> int: + """Gets the register value of the given motor axis driver.""" + ... + async def get_motion_params(self, axis: StackerAxis) -> MoveParams: """Get the motion parameters used by the given axis motor.""" ... + async def get_stallguard_threshold(self, axis: StackerAxis) -> StallGuardParams: + """Get the stallguard parameters by the given axis motor.""" + ... + async def get_limit_switch(self, axis: StackerAxis, direction: Direction) -> bool: """Get limit switch status. @@ -96,16 +118,26 @@ async def move_to_limit_switch( """Move until limit switch is triggered.""" ... - async def home_axis(self, axis: StackerAxis, direction: Direction) -> bool: + async def home_axis(self, axis: StackerAxis, direction: Direction) -> MoveResult: """Home axis.""" ... async def set_led( - self, power: float, color: LEDColor | None = None, external: bool | None = None + self, + power: float, + color: Optional[LEDColor] = None, + external: Optional[bool] = None, + pattern: Optional[LEDPattern] = None, + duration: Optional[int] = None, + reps: Optional[int] = None, ) -> bool: - """Set LED color of status bar.""" + """Set LED Status bar color and pattern.""" ... async def enter_programming_mode(self) -> None: """Reboot into programming mode""" ... + + def reset_serial_buffers(self) -> None: + """Reset the input and output serial buffers.""" + ... diff --git a/api/src/opentrons/drivers/flex_stacker/driver.py b/api/src/opentrons/drivers/flex_stacker/driver.py index 449233d1dee..270cd759f90 100644 --- a/api/src/opentrons/drivers/flex_stacker/driver.py +++ b/api/src/opentrons/drivers/flex_stacker/driver.py @@ -2,12 +2,14 @@ import re from typing import List, Optional +from opentrons.drivers.asyncio.communication.errors import MotorStall from opentrons.drivers.command_builder import CommandBuilder from opentrons.drivers.asyncio.communication import AsyncResponseSerialConnection from .abstract import AbstractFlexStackerDriver from .types import ( GCODE, + LEDPattern, MoveResult, StackerAxis, PlatformStatus, @@ -17,17 +19,30 @@ MoveParams, LimitSwitchStatus, LEDColor, + StallGuardParams, ) FS_BAUDRATE = 115200 -DEFAULT_FS_TIMEOUT = 40 +DEFAULT_FS_TIMEOUT = 1 +FS_MOVE_TIMEOUT = 20 FS_ACK = "OK\n" FS_ERROR_KEYWORD = "err" FS_ASYNC_ERROR_ACK = "async" DEFAULT_COMMAND_RETRIES = 0 GCODE_ROUNDING_PRECISION = 2 +# LED animation range values +MIN_DURATION_MS = 25 # 25ms +MAX_DURATION_MS = 10000 # 10s +MAX_REPS = 10 + +# Stallguard defaults +STALLGUARD_CONFIG = { + StackerAxis.X: StallGuardParams(StackerAxis.X, True, 2), + StackerAxis.Z: StallGuardParams(StackerAxis.Z, True, 2), + StackerAxis.L: StallGuardParams(StackerAxis.L, True, 2), +} STACKER_MOTION_CONFIG = { StackerAxis.X: { @@ -98,6 +113,15 @@ def parse_device_info(cls, response: str) -> StackerInfo: m.group("fw"), HardwareRevision(m.group("hw")), m.group("sn") ) + @classmethod + def parse_reset_reason(cls, response: str) -> int: + """Parse the reset reason""" + _RE = re.compile(rf"^{GCODE.GET_RESET_REASON} R:(?P\d)$") + match = _RE.match(response) + if not match: + raise ValueError(f"Incorrect Response for reset reason: {response}") + return int(match.group("R")) + @classmethod def parse_limit_switch_status(cls, response: str) -> LimitSwitchStatus: """Parse limit switch statuses.""" @@ -123,7 +147,7 @@ def parse_platform_sensor_status(cls, response: str) -> PlatformStatus: @classmethod def parse_door_closed(cls, response: str) -> bool: """Parse door closed.""" - _RE = re.compile(r"^M122 D:(\d)$") + _RE = re.compile(rf"^{GCODE.GET_DOOR_SWITCH} D:(\d)$") match = _RE.match(response) if not match: raise ValueError(f"Incorrect Response for door closed: {response}") @@ -135,7 +159,7 @@ def parse_move_params(cls, response: str) -> MoveParams: field_names = MoveParams.get_fields() pattern = r"\s".join( [ - rf"{f}:(?P<{f}>(\d*\.)?\d+)" if f != "M" else rf"{f}:(?P<{f}>[X,Z,L])" + rf"{f}:(?P<{f}>(\d*\.)?\d+)" if f != "M" else rf"{f}:(?P<{f}>[XZL])" for f in field_names ] ) @@ -150,6 +174,32 @@ def parse_move_params(cls, response: str) -> MoveParams: max_speed_discont=float(m.group("D")), ) + @classmethod + def parse_stallguard_params(cls, response: str) -> StallGuardParams: + """Parse stallguard params.""" + pattern = r"(?P[XZL]):(?P\d) T:(?P\d+)" + _RE = re.compile(f"^{GCODE.GET_STALLGUARD_THRESHOLD} {pattern}$") + m = _RE.match(response) + if not m: + raise ValueError(f"Incorrect Response for stallfguard params: {response}") + return StallGuardParams( + axis=StackerAxis(m.group("M")), + enabled=bool(int(m.group("E"))), + threshold=int(m.group("T")), + ) + + @classmethod + def parse_get_motor_register(cls, response: str) -> int: + """Parse get register value.""" + pattern = r"(?P[XZL]):(?P\d+) V:(?P\d+)" + _RE = re.compile(f"^{GCODE.GET_MOTOR_DRIVER_REGISTER} {pattern}$") + m = _RE.match(response) + if not m: + raise ValueError( + f"Incorrect Response for get motor driver register: {response}" + ) + return int(m.group("V")) + @classmethod def append_move_params( cls, command: CommandBuilder, params: MoveParams | None @@ -209,12 +259,21 @@ async def get_device_info(self) -> StackerInfo: response = await self._connection.send_command( GCODE.DEVICE_INFO.build_command() ) - await self._connection.send_command(GCODE.GET_RESET_REASON.build_command()) - return self.parse_device_info(response) + device_info = self.parse_device_info(response) + reason_resp = await self._connection.send_command( + GCODE.GET_RESET_REASON.build_command() + ) + reason = self.parse_reset_reason(reason_resp) + device_info.rr = reason + return device_info async def set_serial_number(self, sn: str) -> bool: """Set Serial Number.""" - # TODO: validate the serial number format + if not re.match(r"^FST[\w]{1}[\d]{2}[\d]{8}[\d]+$", sn): + raise ValueError( + f"Invalid serial number: ({sn}) expected format: FSTA1020250119001" + ) + resp = await self._connection.send_command( GCODE.SET_SERIAL_NUMBER.build_command().add_element(sn) ) @@ -257,6 +316,46 @@ async def set_ihold_current(self, axis: StackerAxis, current: float) -> bool: raise ValueError(f"Incorrect Response for set ihold current: {resp}") return True + async def set_stallguard_threshold( + self, axis: StackerAxis, enable: bool, threshold: int + ) -> bool: + """Enables and sets the stallguard threshold for the given axis motor.""" + if not -64 < threshold < 63: + raise ValueError( + f"Threshold value ({threshold}) should be between -64 and 63." + ) + + resp = await self._connection.send_command( + GCODE.SET_STALLGUARD.build_command() + .add_int(axis.name, int(enable)) + .add_int("T", threshold) + ) + if not re.match(rf"^{GCODE.SET_STALLGUARD}$", resp): + raise ValueError(f"Incorrect Response for set stallguard threshold: {resp}") + return True + + async def set_motor_driver_register( + self, axis: StackerAxis, reg: int, value: int + ) -> bool: + """Set the register of the given motor axis driver to the given value.""" + resp = await self._connection.send_command( + GCODE.SET_MOTOR_DRIVER_REGISTER.build_command() + .add_int(axis.name, reg) + .add_element(str(value)) + ) + if not re.match(rf"^{GCODE.SET_MOTOR_DRIVER_REGISTER}$", resp): + raise ValueError( + f"Incorrect Response for set motor driver register: {resp}" + ) + return True + + async def get_motor_driver_register(self, axis: StackerAxis, reg: int) -> int: + """Gets the register value of the given motor axis driver.""" + response = await self._connection.send_command( + GCODE.GET_MOTOR_DRIVER_REGISTER.build_command().add_int(axis.name, reg) + ) + return self.parse_get_motor_register(response) + async def get_motion_params(self, axis: StackerAxis) -> MoveParams: """Get the motion parameters used by the given axis motor.""" response = await self._connection.send_command( @@ -264,6 +363,13 @@ async def get_motion_params(self, axis: StackerAxis) -> MoveParams: ) return self.parse_move_params(response) + async def get_stallguard_threshold(self, axis: StackerAxis) -> StallGuardParams: + """Get the stallguard parameters by the given axis motor.""" + response = await self._connection.send_command( + GCODE.GET_STALLGUARD_THRESHOLD.build_command().add_element(axis.name) + ) + return self.parse_stallguard_params(response) + async def get_limit_switch(self, axis: StackerAxis, direction: Direction) -> bool: """Get limit switch status. @@ -314,10 +420,13 @@ async def move_in_mm( ), params, ) - resp = await self._connection.send_command(command) - if not re.match(rf"^{GCODE.MOVE_TO}$", resp): - raise ValueError(f"Incorrect Response for move to: {resp}") - # TODO: handle STALL_ERROR + try: + resp = await self._connection.send_command(command, timeout=FS_MOVE_TIMEOUT) + if not re.match(rf"^{GCODE.MOVE_TO}$", resp): + raise ValueError(f"Incorrect Response for move to: {resp}") + except MotorStall: + self.reset_serial_buffers() + return MoveResult.STALL_ERROR return MoveResult.NO_ERROR async def move_to_limit_switch( @@ -328,29 +437,44 @@ async def move_to_limit_switch( GCODE.MOVE_TO_SWITCH.build_command().add_int(axis.name, direction.value), params, ) - resp = await self._connection.send_command(command) - if not re.match(rf"^{GCODE.MOVE_TO_SWITCH}$", resp): - raise ValueError(f"Incorrect Response for move to switch: {resp}") - # TODO: handle STALL_ERROR + try: + resp = await self._connection.send_command(command, timeout=FS_MOVE_TIMEOUT) + if not re.match(rf"^{GCODE.MOVE_TO_SWITCH}$", resp): + raise ValueError(f"Incorrect Response for move to switch: {resp}") + except MotorStall: + self.reset_serial_buffers() + return MoveResult.STALL_ERROR return MoveResult.NO_ERROR - async def home_axis(self, axis: StackerAxis, direction: Direction) -> bool: + async def home_axis(self, axis: StackerAxis, direction: Direction) -> MoveResult: """Home axis.""" - resp = await self._connection.send_command( - GCODE.HOME_AXIS.build_command().add_int(axis.name, direction.value) - ) + command = GCODE.HOME_AXIS.build_command().add_int(axis.name, direction.value) + try: + resp = await self._connection.send_command(command, timeout=FS_MOVE_TIMEOUT) + except MotorStall: + self.reset_serial_buffers() + return MoveResult.STALL_ERROR if not re.match(rf"^{GCODE.HOME_AXIS}$", resp): raise ValueError(f"Incorrect Response for home axis: {resp}") - return True + return MoveResult.NO_ERROR async def set_led( - self, power: float, color: LEDColor | None = None, external: bool | None = None + self, + power: float, + color: Optional[LEDColor] = None, + external: Optional[bool] = None, + pattern: Optional[LEDPattern] = None, + duration: Optional[int] = None, + reps: Optional[int] = None, ) -> bool: - """Set LED color. + """Set LED Status bar color and pattern. :param power: Power of the LED (0-1.0), 0 is off, 1 is full power :param color: Color of the LED :param external: True if external LED, False if internal LED + :param pattern: Animation pattern of the LED status bar + :param duration: Animation duration in milliseconds (25-10000), 10s max + :param reps: Number of times to repeat the animation (-1 - 10), -1 is forever. """ power = max(0, min(power, 1.0)) command = GCODE.SET_LED.build_command().add_float( @@ -359,7 +483,14 @@ async def set_led( if color is not None: command.add_int("C", color.value) if external is not None: - command.add_int("E", external) + command.add_int("K", int(external)) + if pattern is not None: + command.add_int("A", pattern.value) + if duration is not None: + duration = max(MIN_DURATION_MS, min(duration, MAX_DURATION_MS)) + command.add_int("D", duration) + if reps is not None: + command.add_int("R", max(-1, min(reps, MAX_REPS))) resp = await self._connection.send_command(command) if not re.match(rf"^{GCODE.SET_LED}$", resp): raise ValueError(f"Incorrect Response for set led: {resp}") @@ -370,3 +501,8 @@ async def enter_programming_mode(self) -> None: command = GCODE.ENTER_BOOTLOADER.build_command() await self._connection.send_dfu_command(command) await self._connection.close() + + def reset_serial_buffers(self) -> None: + """Reset the input and output serial buffers.""" + self._connection._serial.reset_input_buffer() + self._connection._serial.reset_output_buffer() diff --git a/api/src/opentrons/drivers/flex_stacker/simulator.py b/api/src/opentrons/drivers/flex_stacker/simulator.py index 1ceedabf146..88195f5ea71 100644 --- a/api/src/opentrons/drivers/flex_stacker/simulator.py +++ b/api/src/opentrons/drivers/flex_stacker/simulator.py @@ -1,10 +1,11 @@ -from typing import List, Optional +from typing import List, Optional, Dict from opentrons.util.async_helpers import ensure_yield from .abstract import AbstractFlexStackerDriver from .types import ( LEDColor, + LEDPattern, MoveResult, StackerAxis, PlatformStatus, @@ -13,6 +14,7 @@ HardwareRevision, MoveParams, LimitSwitchStatus, + StallGuardParams, ) @@ -24,6 +26,13 @@ def __init__(self, serial_number: Optional[str] = None) -> None: self._limit_switch_status = LimitSwitchStatus(False, False, False, False, False) self._platform_sensor_status = PlatformStatus(False, False) self._door_closed = True + self._connected = True + self._stallgard_threshold = { + a: StallGuardParams(a, False, 0) for a in StackerAxis + } + self._motor_registers: Dict[StackerAxis, Dict[int, int]] = { + a: {} for a in StackerAxis + } def set_limit_switch(self, status: LimitSwitchStatus) -> bool: self._limit_switch_status = status @@ -40,17 +49,17 @@ def set_door_closed(self, door_closed: bool) -> bool: @ensure_yield async def connect(self) -> None: """Connect to stacker.""" - pass + self._connected = True @ensure_yield async def disconnect(self) -> None: """Disconnect from stacker.""" - pass + self._connected = False @ensure_yield async def is_connected(self) -> bool: """Check connection to stacker.""" - return True + return self._connected @ensure_yield async def get_device_info(self) -> StackerInfo: @@ -60,6 +69,7 @@ async def get_device_info(self) -> StackerInfo: @ensure_yield async def set_serial_number(self, sn: str) -> bool: """Set Serial Number.""" + self._sn = sn return True async def enable_motors(self, axis: List[StackerAxis]) -> bool: @@ -73,16 +83,39 @@ async def stop_motors(self) -> bool: async def set_run_current(self, axis: StackerAxis, current: float) -> bool: """Set axis peak run current in amps.""" + return True async def set_ihold_current(self, axis: StackerAxis, current: float) -> bool: """Set axis hold current in amps.""" return True + async def set_stallguard_threshold( + self, axis: StackerAxis, enable: bool, threshold: int + ) -> bool: + """Enables and sets the stallguard threshold for the given axis motor.""" + self._stallgard_threshold[axis] = StallGuardParams(axis, enable, threshold) + return True + + async def set_motor_driver_register( + self, axis: StackerAxis, reg: int, value: int + ) -> bool: + """Set the register of the given motor axis driver to the given value.""" + self._motor_registers[axis].update({reg: value}) + return True + + async def get_motor_driver_register(self, axis: StackerAxis, reg: int) -> int: + """Gets the register value of the given motor axis driver.""" + return self._motor_registers[axis].get(reg, 0) + async def get_motion_params(self, axis: StackerAxis) -> MoveParams: """Get the motion parameters used by the given axis motor.""" return MoveParams(axis, 1, 1, 1) + async def get_stallguard_threshold(self, axis: StackerAxis) -> StallGuardParams: + """Get the stallguard parameters by the given axis motor.""" + return self._stallgard_threshold[axis] + @ensure_yield async def get_limit_switch(self, axis: StackerAxis, direction: Direction) -> bool: """Get limit switch status. @@ -101,7 +134,7 @@ async def get_platform_sensor(self, direction: Direction) -> bool: :return: True if platform is present, False otherwise """ - return True + return self._platform_sensor_status.get(direction) async def get_platform_status(self) -> PlatformStatus: """Get platform status.""" @@ -129,16 +162,26 @@ async def move_to_limit_switch( """Move until limit switch is triggered.""" return MoveResult.NO_ERROR - async def home_axis(self, axis: StackerAxis, direction: Direction) -> bool: + async def home_axis(self, axis: StackerAxis, direction: Direction) -> MoveResult: """Home axis.""" - return True + return MoveResult.NO_ERROR async def set_led( - self, power: float, color: LEDColor | None = None, external: bool | None = None + self, + power: float, + color: Optional[LEDColor] = None, + external: Optional[bool] = None, + pattern: Optional[LEDPattern] = None, + duration: Optional[int] = None, + reps: Optional[int] = None, ) -> bool: - """Set LED color.""" + """Set LED Status bar color and pattern.""" return True async def enter_programming_mode(self) -> None: """Reboot into programming mode""" pass + + def reset_serial_buffers(self) -> None: + """Reset the input and output serial buffers.""" + pass diff --git a/api/src/opentrons/drivers/flex_stacker/types.py b/api/src/opentrons/drivers/flex_stacker/types.py index 9f8e8825b93..3a2bff11814 100644 --- a/api/src/opentrons/drivers/flex_stacker/types.py +++ b/api/src/opentrons/drivers/flex_stacker/types.py @@ -18,10 +18,14 @@ class GCODE(str, Enum): GET_MOVE_PARAMS = "M120" GET_PLATFORM_SENSOR = "M121" GET_DOOR_SWITCH = "M122" + GET_STALLGUARD_THRESHOLD = "M911" + GET_MOTOR_DRIVER_REGISTER = "M920" SET_LED = "M200" SET_SERIAL_NUMBER = "M996" SET_RUN_CURRENT = "M906" SET_IHOLD_CURRENT = "M907" + SET_STALLGUARD = "M910" + SET_MOTOR_DRIVER_REGISTER = "M921" ENTER_BOOTLOADER = "dfu" def build_command(self) -> CommandBuilder: @@ -48,6 +52,7 @@ class StackerInfo: fw: str hw: HardwareRevision sn: str + rr: int = 0 def to_dict(self) -> Dict[str, str]: """Build command.""" @@ -55,6 +60,7 @@ def to_dict(self) -> Dict[str, str]: "serial": self.sn, "version": self.fw, "model": self.hw.value, + "reset_reason": str(self.rr), } @@ -77,13 +83,23 @@ class LEDColor(Enum): RED = 1 GREEN = 2 BLUE = 3 + YELLOW = 4 + + +class LEDPattern(Enum): + """Stacker LED Pattern.""" + + STATIC = 0 + FLASH = 1 + PULSE = 2 + CONFIRM = 3 class Direction(Enum): """Direction.""" RETRACT = 0 # negative - EXTENT = 1 # positive + EXTEND = 1 # positive def __str__(self) -> str: """Convert to tag for clear logging.""" @@ -91,7 +107,7 @@ def __str__(self) -> str: def opposite(self) -> "Direction": """Get opposite direction.""" - return Direction.EXTENT if self == Direction.RETRACT else Direction.RETRACT + return Direction.EXTEND if self == Direction.RETRACT else Direction.RETRACT def distance(self, distance: float) -> float: """Get signed distance, where retract direction is negative.""" @@ -116,10 +132,10 @@ def get_fields(cls) -> List[str]: def get(self, axis: StackerAxis, direction: Direction) -> bool: """Get limit switch status.""" if axis == StackerAxis.X: - return self.XE if direction == Direction.EXTENT else self.XR + return self.XE if direction == Direction.EXTEND else self.XR if axis == StackerAxis.Z: - return self.ZE if direction == Direction.EXTENT else self.ZR - if direction == Direction.EXTENT: + return self.ZE if direction == Direction.EXTEND else self.ZR + if direction == Direction.EXTEND: raise ValueError("Latch does not have extent limit switch") return self.LR @@ -138,7 +154,7 @@ def get_fields(cls) -> List[str]: def get(self, direction: Direction) -> bool: """Get platform status.""" - return self.E if direction == Direction.EXTENT else self.R + return self.E if direction == Direction.EXTEND else self.R def to_dict(self) -> Dict[str, bool]: """Dict of the data.""" @@ -164,6 +180,15 @@ def get_fields(cls) -> List[str]: return ["M", "V", "A", "D"] +@dataclass +class StallGuardParams: + """StallGuard Parameters.""" + + axis: StackerAxis + enabled: bool + threshold: int + + class MoveResult(str, Enum): """The result of a move command.""" diff --git a/api/src/opentrons/hardware_control/modules/errors.py b/api/src/opentrons/hardware_control/modules/errors.py index 46601a0aa2a..b79ab4d79ed 100644 --- a/api/src/opentrons/hardware_control/modules/errors.py +++ b/api/src/opentrons/hardware_control/modules/errors.py @@ -1,3 +1,6 @@ +from opentrons.drivers.flex_stacker.types import StackerAxis + + class UpdateError(RuntimeError): pass @@ -5,3 +8,9 @@ class UpdateError(RuntimeError): class AbsorbanceReaderDisconnectedError(RuntimeError): def __init__(self, serial: str): self.serial = serial + + +class FlexStackerStallError(RuntimeError): + def __init__(self, serial: str, axis: StackerAxis): + self.serial = serial + self.axis = axis diff --git a/api/src/opentrons/hardware_control/modules/flex_stacker.py b/api/src/opentrons/hardware_control/modules/flex_stacker.py index 686653a2f24..136ac1d18bc 100644 --- a/api/src/opentrons/hardware_control/modules/flex_stacker.py +++ b/api/src/opentrons/hardware_control/modules/flex_stacker.py @@ -6,6 +6,8 @@ from opentrons.drivers.flex_stacker.types import ( Direction, + LEDColor, + LEDPattern, MoveParams, MoveResult, StackerAxis, @@ -13,11 +15,13 @@ from opentrons.drivers.rpi_drivers.types import USBPort from opentrons.drivers.flex_stacker.driver import ( STACKER_MOTION_CONFIG, + STALLGUARD_CONFIG, FlexStackerDriver, ) from opentrons.drivers.flex_stacker.abstract import AbstractFlexStackerDriver from opentrons.drivers.flex_stacker.simulator import SimulatingDriver from opentrons.hardware_control.execution_manager import ExecutionManager +from opentrons.hardware_control.modules.errors import FlexStackerStallError from opentrons.hardware_control.poller import Reader, Poller from opentrons.hardware_control.modules import mod_abc, update from opentrons.hardware_control.modules.types import ( @@ -116,6 +120,13 @@ async def build( disconnected_callback=disconnected_callback, ) + # Enable stallguard + for axis in StackerAxis: + config = STALLGUARD_CONFIG[axis] + await driver.set_stallguard_threshold( + axis, config.enabled, config.threshold + ) + try: await poller.start() except Exception: @@ -147,6 +158,7 @@ def __init__( self._reader = reader self._poller = poller self._stacker_status = FlexStackerStatus.IDLE + self._stall_detected = False async def cleanup(self) -> None: """Stop the poller task""" @@ -229,6 +241,25 @@ def bootloader(self) -> UploadFunction: async def deactivate(self, must_be_running: bool = True) -> None: await self._driver.stop_motors() + async def reset_stall_detected(self) -> None: + """Sets the statusbar to normal.""" + if self._stall_detected: + await self.set_led_state(0.5, LEDColor.GREEN, LEDPattern.STATIC) + self._stall_detected = False + + async def set_led_state( + self, + power: float, + color: Optional[LEDColor] = None, + pattern: Optional[LEDPattern] = None, + duration: Optional[int] = None, + reps: Optional[int] = None, + ) -> bool: + """Sets the statusbar state.""" + return await self._driver.set_led( + power, color=color, pattern=pattern, duration=duration, reps=reps + ) + async def move_axis( self, axis: StackerAxis, @@ -239,15 +270,18 @@ async def move_axis( current: Optional[float] = None, ) -> bool: """Move the axis in a direction by the given distance in mm.""" + await self.reset_stall_detected() motion_params = STACKER_MOTION_CONFIG[axis]["move"] await self._driver.set_run_current(axis, current or motion_params.current or 0) if any([speed, acceleration]): motion_params.max_speed = speed or motion_params.max_speed motion_params.acceleration = acceleration or motion_params.acceleration distance = direction.distance(distance) - success = await self._driver.move_in_mm(axis, distance, params=motion_params) - # TODO: This can return a stall, handle that here - return success == MoveResult.NO_ERROR + res = await self._driver.move_in_mm(axis, distance, params=motion_params) + if res == MoveResult.STALL_ERROR: + self._stall_detected = True + raise FlexStackerStallError(self.device_info["serial"], axis) + return res == MoveResult.NO_ERROR async def home_axis( self, @@ -257,6 +291,7 @@ async def home_axis( acceleration: Optional[float] = None, current: Optional[float] = None, ) -> bool: + await self.reset_stall_detected() motion_params = STACKER_MOTION_CONFIG[axis]["home"] await self._driver.set_run_current(axis, current or motion_params.current or 0) # Set the max hold current for the Z axis @@ -268,7 +303,9 @@ async def home_axis( success = await self._driver.move_to_limit_switch( axis=axis, direction=direction, params=motion_params ) - # TODO: This can return a stall, handle that here + if success == MoveResult.STALL_ERROR: + self._stall_detected = True + raise FlexStackerStallError(self.device_info["serial"], axis) return success == MoveResult.NO_ERROR async def close_latch( @@ -313,7 +350,7 @@ async def open_latch( # to open the latch. success = await self.move_axis( StackerAxis.L, - Direction.EXTENT, + Direction.EXTEND, distance=distance, speed=speed, acceleration=accel, @@ -329,7 +366,7 @@ async def dispense_labware(self, labware_height: float) -> bool: # Move platform along the X then Z axis await self._move_and_home_axis(StackerAxis.X, Direction.RETRACT, OFFSET_SM) - await self._move_and_home_axis(StackerAxis.Z, Direction.EXTENT, OFFSET_SM) + await self._move_and_home_axis(StackerAxis.Z, Direction.EXTEND, OFFSET_SM) # Transfer await self.open_latch() @@ -339,7 +376,7 @@ async def dispense_labware(self, labware_height: float) -> bool: # Move platform along the Z then X axis offset = labware_height / 2 + OFFSET_MD await self._move_and_home_axis(StackerAxis.Z, Direction.RETRACT, offset) - await self._move_and_home_axis(StackerAxis.X, Direction.EXTENT, OFFSET_SM) + await self._move_and_home_axis(StackerAxis.X, Direction.EXTEND, OFFSET_SM) return True async def store_labware(self, labware_height: float) -> bool: @@ -350,17 +387,17 @@ async def store_labware(self, labware_height: float) -> bool: offset = OFFSET_MD if labware_height < MEDIUM_LABWARE_Z_LIMIT else OFFSET_LG * 2 distance = MAX_TRAVEL[StackerAxis.Z] - (labware_height / 2) - offset await self._move_and_home_axis(StackerAxis.X, Direction.RETRACT, OFFSET_SM) - await self.move_axis(StackerAxis.Z, Direction.EXTENT, distance) + await self.move_axis(StackerAxis.Z, Direction.EXTEND, distance) # Transfer await self.open_latch() - await self.move_axis(StackerAxis.Z, Direction.EXTENT, (labware_height / 2)) - await self.home_axis(StackerAxis.Z, Direction.EXTENT) + await self.move_axis(StackerAxis.Z, Direction.EXTEND, (labware_height / 2)) + await self.home_axis(StackerAxis.Z, Direction.EXTEND) await self.close_latch() # Move Z then X axis await self._move_and_home_axis(StackerAxis.Z, Direction.RETRACT, OFFSET_LG) - await self._move_and_home_axis(StackerAxis.X, Direction.EXTENT, OFFSET_SM) + await self._move_and_home_axis(StackerAxis.X, Direction.EXTEND, OFFSET_SM) return True async def _move_and_home_axis( @@ -373,7 +410,7 @@ async def _move_and_home_axis( async def _prepare_for_action(self) -> bool: """Helper to prepare axis for dispensing or storing labware.""" # TODO: check if we need to home first - await self.home_axis(StackerAxis.X, Direction.EXTENT) + await self.home_axis(StackerAxis.X, Direction.EXTEND) await self.home_axis(StackerAxis.Z, Direction.RETRACT) await self.close_latch() return True @@ -406,9 +443,7 @@ async def get_limit_switch_status(self) -> None: """Get the limit switch status.""" status = await self._driver.get_limit_switches_status() self.limit_switch_status = { - StackerAxis.X: StackerAxisState.from_status(status, StackerAxis.X), - StackerAxis.Z: StackerAxisState.from_status(status, StackerAxis.Z), - StackerAxis.L: StackerAxisState.from_status(status, StackerAxis.L), + axis: StackerAxisState.from_status(status, axis) for axis in StackerAxis } async def get_motion_parameters(self) -> None: @@ -427,6 +462,7 @@ async def get_door_closed(self) -> None: self.hopper_door_closed = await self._driver.get_hopper_door_closed() def on_error(self, exception: Exception) -> None: + self._driver.reset_serial_buffers() self._set_error(exception) def _set_error(self, exception: Optional[Exception]) -> None: diff --git a/api/tests/opentrons/drivers/flex_stacker/test_driver.py b/api/tests/opentrons/drivers/flex_stacker/test_driver.py index 1de13c569cb..1c77e381e9b 100644 --- a/api/tests/opentrons/drivers/flex_stacker/test_driver.py +++ b/api/tests/opentrons/drivers/flex_stacker/test_driver.py @@ -3,7 +3,7 @@ from opentrons.drivers.asyncio.communication.serial_connection import ( AsyncResponseSerialConnection, ) -from opentrons.drivers.flex_stacker.driver import FlexStackerDriver +from opentrons.drivers.flex_stacker.driver import FS_MOVE_TIMEOUT, FlexStackerDriver from opentrons.drivers.flex_stacker import types @@ -22,14 +22,16 @@ async def test_get_device_info( subject: FlexStackerDriver, connection: AsyncMock ) -> None: """It should send a get device info command""" - connection.send_command.return_value = ( - "M115 FW:0.0.1 HW:Opentrons-flex-stacker-a1 SerialNo:STCA120230605001" - ) + connection.send_command.side_effect = [ + "M115 FW:0.0.1 HW:Opentrons-flex-stacker-a1 SerialNo:STCA120230605001", + "M114 R:0", + ] response = await subject.get_device_info() assert response == types.StackerInfo( fw="0.0.1", hw=types.HardwareRevision.EVT, sn="STCA120230605001", + rr=0, ) device_info = types.GCODE.DEVICE_INFO.build_command() @@ -39,16 +41,19 @@ async def test_get_device_info( connection.reset_mock() # Test invalid response - connection.send_command.return_value = "M115 FW:0.0.1 SerialNo:STCA120230605001" + connection.send_command.side_effect = [ + "M115 FW:0.0.1 SerialNo:STCA120230605001", + "M114 R:0", + ] # This should raise ValueError with pytest.raises(ValueError): response = await subject.get_device_info() device_info = types.GCODE.DEVICE_INFO.build_command() - reset_reason = types.GCODE.GET_RESET_REASON.build_command() connection.send_command.assert_any_call(device_info) - connection.send_command.assert_called_with(reset_reason) + # M115 response is invalid, so we dont send M114. + connection.send_command.assert_called_once() async def test_stop_motors(subject: FlexStackerDriver, connection: AsyncMock) -> None: @@ -93,7 +98,7 @@ async def test_set_serial_number( """It should send a set serial number command""" connection.send_command.return_value = "M996" - serial_number = "Something" + serial_number = "FSTA1020250119001" response = await subject.set_serial_number(serial_number) assert response @@ -114,6 +119,13 @@ async def test_set_serial_number( connection.send_command.assert_any_call(set_serial_number) connection.reset_mock() + # Test invalid serial number + with pytest.raises(ValueError): + response = await subject.set_serial_number("invalid") + + connection.send_command.assert_not_called() + connection.reset_mock() + async def test_enable_motors(subject: FlexStackerDriver, connection: AsyncMock) -> None: """It should send a enable motors command""" @@ -147,7 +159,7 @@ async def test_get_limit_switch( """It should send a get limit switch command and return the boolean of one.""" connection.send_command.return_value = "M119 XE:1 XR:0 ZE:0 ZR:1 LR:1" response = await subject.get_limit_switch( - types.StackerAxis.X, types.Direction.EXTENT + types.StackerAxis.X, types.Direction.EXTEND ) assert response @@ -188,7 +200,7 @@ async def test_get_platform_sensor( ) -> None: """It should send a get platform sensor command return status of specified sensor.""" connection.send_command.return_value = "M121 E:1 R:1" - response = await subject.get_platform_sensor(types.Direction.EXTENT) + response = await subject.get_platform_sensor(types.Direction.EXTEND) assert response platform_sensor = types.GCODE.GET_PLATFORM_SENSOR.build_command() @@ -259,7 +271,7 @@ async def test_move_in_mm(subject: FlexStackerDriver, connection: AsyncMock) -> assert response move_to = types.GCODE.MOVE_TO.build_command().add_float("X", 10) - connection.send_command.assert_any_call(move_to) + connection.send_command.assert_any_call(move_to, timeout=FS_MOVE_TIMEOUT) connection.reset_mock() @@ -269,14 +281,14 @@ async def test_move_to_switch( """It should send a move to switch command""" connection.send_command.return_value = "G5" axis = types.StackerAxis.X - direction = types.Direction.EXTENT + direction = types.Direction.EXTEND response = await subject.move_to_limit_switch(axis, direction) assert response move_to = types.GCODE.MOVE_TO_SWITCH.build_command().add_int( axis.name, direction.value ) - connection.send_command.assert_any_call(move_to) + connection.send_command.assert_any_call(move_to, timeout=FS_MOVE_TIMEOUT) connection.reset_mock() @@ -284,12 +296,12 @@ async def test_home_axis(subject: FlexStackerDriver, connection: AsyncMock) -> N """It should send a home axis command""" connection.send_command.return_value = "G28" axis = types.StackerAxis.X - direction = types.Direction.EXTENT + direction = types.Direction.EXTEND response = await subject.home_axis(axis, direction) assert response move_to = types.GCODE.HOME_AXIS.build_command().add_int(axis.name, direction.value) - connection.send_command.assert_any_call(move_to) + connection.send_command.assert_any_call(move_to, timeout=FS_MOVE_TIMEOUT) connection.reset_mock() @@ -302,3 +314,90 @@ async def test_set_led(subject: FlexStackerDriver, connection: AsyncMock) -> Non set_led = types.GCODE.SET_LED.build_command().add_float("P", 1).add_int("C", 1) connection.send_command.assert_any_call(set_led) connection.reset_mock() + + # test setting only external leds + response = await subject.set_led(1, types.LEDColor.RED, external=True) + assert response + + set_led = ( + types.GCODE.SET_LED.build_command() + .add_float("P", 1) + .add_int("C", 1) + .add_int("K", 1) + ) + connection.send_command.assert_any_call(set_led) + connection.reset_mock() + + +async def test_get_stallguard_threshold( + subject: FlexStackerDriver, connection: AsyncMock +) -> None: + """It should get the stallguard threshold.""" + connection.send_command.return_value = "M911 Z:1 T:2" + response = await subject.get_stallguard_threshold(types.StackerAxis.Z) + assert response == types.StallGuardParams(types.StackerAxis.Z, True, 2) + + get_theshold = types.GCODE.GET_STALLGUARD_THRESHOLD.build_command().add_element( + types.StackerAxis.Z.name + ) + connection.send_command.assert_any_call(get_theshold) + connection.reset_mock() + + +async def test_set_stallguard_threshold( + subject: FlexStackerDriver, connection: AsyncMock +) -> None: + """It should set the stallguard threshold.""" + axis = types.StackerAxis.Z + enable = True + threshold = 2 + connection.send_command.return_value = "M910" + response = await subject.set_stallguard_threshold(axis, enable, threshold) + assert response + + set_threshold = ( + types.GCODE.SET_STALLGUARD.build_command() + .add_int(axis.name, int(enable)) + .add_int("T", threshold) + ) + connection.send_command.assert_any_call(set_threshold) + connection.reset_mock() + + # test invalid threshold + with pytest.raises(ValueError): + response = await subject.set_stallguard_threshold(axis, enable, 1000) + + connection.send_command.assert_not_called() + connection.reset_mock() + + +async def test_get_motor_driver_register( + subject: FlexStackerDriver, connection: AsyncMock +) -> None: + """It should get the motor driver register.""" + connection.send_command.return_value = "M920 Z:1 V:2" + response = await subject.get_motor_driver_register(types.StackerAxis.Z, 1) + assert response == 2 + + get_register = types.GCODE.GET_MOTOR_DRIVER_REGISTER.build_command().add_int( + types.StackerAxis.Z.name, 1 + ) + connection.send_command.assert_any_call(get_register) + connection.reset_mock() + + +async def test_set_motor_driver_register( + subject: FlexStackerDriver, connection: AsyncMock +) -> None: + """It should set the motor driver register.""" + connection.send_command.return_value = "M921" + response = await subject.set_motor_driver_register(types.StackerAxis.Z, 1, 2) + assert response + + set_register = ( + types.GCODE.SET_MOTOR_DRIVER_REGISTER.build_command() + .add_int(types.StackerAxis.Z.name, 1) + .add_element(str(2)) + ) + connection.send_command.assert_any_call(set_register) + connection.reset_mock() From 266148833070577775cc8ce8437feb9188a5d125 Mon Sep 17 00:00:00 2001 From: Ryan Howard Date: Wed, 29 Jan 2025 10:01:47 -0500 Subject: [PATCH 15/22] fix(api): Use the latest information when estimating liquid height (#17374) # Overview There was a bug in the estimation code under the following scenario Well volume is set with Load Liquid Well is then probed Well is operated on and the probed volume and loaded volume are updated based on the operation Future well operations are based on the load liquid and not the probe because it happened to be first in the "is_valid" check Now the well volume after an operation is based on which happened LAST load_liquid or liquid probe. ## Test Plan and Hands on Testing ## Changelog ## Review requests ## Risk assessment --- .../protocol_engine/state/geometry.py | 12 +- .../opentrons/protocol_engine/state/wells.py | 17 ++ .../state/test_geometry_view.py | 166 +++++++++++++++++- 3 files changed, 187 insertions(+), 8 deletions(-) diff --git a/api/src/opentrons/protocol_engine/state/geometry.py b/api/src/opentrons/protocol_engine/state/geometry.py index cf6b4521713..9a817564c67 100644 --- a/api/src/opentrons/protocol_engine/state/geometry.py +++ b/api/src/opentrons/protocol_engine/state/geometry.py @@ -1448,17 +1448,25 @@ def get_meniscus_height( well_name: str, ) -> float: """Returns stored meniscus height in specified well.""" + last_updated = self._wells.get_last_liquid_update(labware_id, well_name) + if last_updated is None: + raise errors.LiquidHeightUnknownError( + "Must LiquidProbe or LoadLiquid before specifying WellOrigin.MENISCUS." + ) + well_liquid = self._wells.get_well_liquid_info( labware_id=labware_id, well_name=well_name ) if ( well_liquid.probed_height is not None and well_liquid.probed_height.height is not None + and well_liquid.probed_height.last_probed == last_updated ): return well_liquid.probed_height.height elif ( well_liquid.loaded_volume is not None and well_liquid.loaded_volume.volume is not None + and well_liquid.loaded_volume.last_loaded == last_updated ): return self.get_well_height_at_volume( labware_id=labware_id, @@ -1468,6 +1476,7 @@ def get_meniscus_height( elif ( well_liquid.probed_volume is not None and well_liquid.probed_volume.volume is not None + and well_liquid.probed_volume.last_probed == last_updated ): return self.get_well_height_at_volume( labware_id=labware_id, @@ -1475,8 +1484,9 @@ def get_meniscus_height( volume=well_liquid.probed_volume.volume, ) else: + # This should not happen if there was an update but who knows raise errors.LiquidHeightUnknownError( - "Must LiquidProbe or LoadLiquid before specifying WellOrigin.MENISCUS." + f"Unable to find liquid height despite an update at {last_updated}." ) def get_well_handling_height( diff --git a/api/src/opentrons/protocol_engine/state/wells.py b/api/src/opentrons/protocol_engine/state/wells.py index fdcb8322094..727ef20da59 100644 --- a/api/src/opentrons/protocol_engine/state/wells.py +++ b/api/src/opentrons/protocol_engine/state/wells.py @@ -2,6 +2,7 @@ from dataclasses import dataclass from typing import Dict, List, Union, Iterator, Optional, Tuple, overload, TypeVar +from datetime import datetime from opentrons.protocol_engine.types import ( ProbedHeightInfo, @@ -177,6 +178,22 @@ def get_well_liquid_info(self, labware_id: str, well_name: str) -> WellLiquidInf probed_volume=probed_volume_info, ) + def get_last_liquid_update( + self, labware_id: str, well_name: str + ) -> Optional[datetime]: + """Return the timestamp of the last load or probe done on the well.""" + info = self.get_well_liquid_info(labware_id, well_name) + update_times: List[datetime] = [] + if info.loaded_volume is not None and info.loaded_volume.volume is not None: + update_times.append(info.loaded_volume.last_loaded) + if info.probed_height is not None and info.probed_height.height is not None: + update_times.append(info.probed_height.last_probed) + if info.probed_volume is not None and info.probed_volume.volume is not None: + update_times.append(info.probed_volume.last_probed) + if len(update_times) > 0: + return max(update_times) + return None + def get_all(self) -> List[WellInfoSummary]: """Get all well liquid info summaries.""" diff --git a/api/tests/opentrons/protocol_engine/state/test_geometry_view.py b/api/tests/opentrons/protocol_engine/state/test_geometry_view.py index bf82c17c6bc..f5f86fc8c4c 100644 --- a/api/tests/opentrons/protocol_engine/state/test_geometry_view.py +++ b/api/tests/opentrons/protocol_engine/state/test_geometry_view.py @@ -62,6 +62,7 @@ TipGeometry, ModuleDefinition, ProbedHeightInfo, + ProbedVolumeInfo, LoadedVolumeInfo, WellLiquidInfo, ) @@ -1577,10 +1578,14 @@ def test_get_well_position_with_meniscus_offset( decoy.when(mock_labware_view.get_well_definition("labware-id", "B2")).then_return( well_def ) + probe_time = datetime.now() + decoy.when(mock_well_view.get_last_liquid_update("labware-id", "B2")).then_return( + probe_time + ) decoy.when(mock_well_view.get_well_liquid_info("labware-id", "B2")).then_return( WellLiquidInfo( probed_volume=None, - probed_height=ProbedHeightInfo(height=70.5, last_probed=datetime.now()), + probed_height=ProbedHeightInfo(height=70.5, last_probed=probe_time), loaded_volume=None, ) ) @@ -1639,10 +1644,14 @@ def test_get_well_position_with_volume_offset_raises_error( decoy.when(mock_labware_view.get_well_definition("labware-id", "B2")).then_return( well_def ) + probe_time = datetime.now() + decoy.when(mock_well_view.get_last_liquid_update("labware-id", "B2")).then_return( + probe_time + ) decoy.when(mock_well_view.get_well_liquid_info("labware-id", "B2")).then_return( WellLiquidInfo( loaded_volume=None, - probed_height=ProbedHeightInfo(height=45.0, last_probed=datetime.now()), + probed_height=ProbedHeightInfo(height=45.0, last_probed=probe_time), probed_volume=None, ) ) @@ -1698,13 +1707,17 @@ def test_get_well_position_with_meniscus_and_literal_volume_offset( decoy.when( mock_addressable_area_view.get_addressable_area_position(DeckSlotName.SLOT_4.id) ).then_return(slot_pos) + probe_time = datetime.now() + decoy.when(mock_well_view.get_last_liquid_update("labware-id", "B2")).then_return( + probe_time + ) decoy.when(mock_labware_view.get_well_definition("labware-id", "B2")).then_return( well_def ) decoy.when(mock_well_view.get_well_liquid_info("labware-id", "B2")).then_return( WellLiquidInfo( loaded_volume=None, - probed_height=ProbedHeightInfo(height=45.0, last_probed=datetime.now()), + probed_height=ProbedHeightInfo(height=45.0, last_probed=probe_time), probed_volume=None, ) ) @@ -1771,10 +1784,14 @@ def test_get_well_position_with_meniscus_and_float_volume_offset( decoy.when(mock_labware_view.get_well_definition("labware-id", "B2")).then_return( well_def ) + probe_time = datetime.now() + decoy.when(mock_well_view.get_last_liquid_update("labware-id", "B2")).then_return( + probe_time + ) decoy.when(mock_well_view.get_well_liquid_info("labware-id", "B2")).then_return( WellLiquidInfo( loaded_volume=None, - probed_height=ProbedHeightInfo(height=45.0, last_probed=datetime.now()), + probed_height=ProbedHeightInfo(height=45.0, last_probed=probe_time), probed_volume=None, ) ) @@ -1840,10 +1857,14 @@ def test_get_well_position_raises_validation_error( decoy.when(mock_labware_view.get_well_definition("labware-id", "B2")).then_return( well_def ) + probe_time = datetime.now() + decoy.when(mock_well_view.get_last_liquid_update("labware-id", "B2")).then_return( + probe_time + ) decoy.when(mock_well_view.get_well_liquid_info("labware-id", "B2")).then_return( WellLiquidInfo( loaded_volume=None, - probed_height=ProbedHeightInfo(height=40.0, last_probed=datetime.now()), + probed_height=ProbedHeightInfo(height=40.0, last_probed=probe_time), probed_volume=None, ) ) @@ -1905,10 +1926,14 @@ def test_get_meniscus_height( decoy.when(mock_labware_view.get_well_definition("labware-id", "B2")).then_return( well_def ) + probe_time = datetime.now() + decoy.when(mock_well_view.get_last_liquid_update("labware-id", "B2")).then_return( + probe_time + ) decoy.when(mock_well_view.get_well_liquid_info("labware-id", "B2")).then_return( WellLiquidInfo( loaded_volume=LoadedVolumeInfo( - volume=2000.0, last_loaded=datetime.now(), operations_since_load=0 + volume=2000.0, last_loaded=probe_time, operations_since_load=0 ), probed_height=None, probed_volume=None, @@ -3349,10 +3374,14 @@ def test_validate_dispense_volume_into_well_meniscus( decoy.when(mock_labware_view.get_well_geometry("labware-id", "A1")).then_return( inner_well_def ) + probe_time = datetime.now() + decoy.when(mock_well_view.get_last_liquid_update("labware-id", "A1")).then_return( + probe_time + ) decoy.when(mock_well_view.get_well_liquid_info("labware-id", "A1")).then_return( WellLiquidInfo( loaded_volume=None, - probed_height=ProbedHeightInfo(height=40.0, last_probed=datetime.now()), + probed_height=ProbedHeightInfo(height=40.0, last_probed=probe_time), probed_volume=None, ) ) @@ -3369,6 +3398,129 @@ def test_validate_dispense_volume_into_well_meniscus( ) +def test_get_latest_volume_information( + decoy: Decoy, + mock_labware_view: LabwareView, + mock_well_view: WellView, + subject: GeometryView, +) -> None: + """It should raise an InvalidDispenseVolumeError if too much volume is specified.""" + # Setup + labware_def = _load_labware_definition_data() + assert labware_def.wells is not None + well_def = labware_def.wells["A1"] + assert labware_def.innerLabwareGeometry is not None + inner_well_def = labware_def.innerLabwareGeometry["welldefinition1111"] + + load_time = datetime.min + probe_time = datetime.now() + + decoy.when(mock_labware_view.get_well_definition("labware-id", "A1")).then_return( + well_def + ) + decoy.when(mock_labware_view.get_well_geometry("labware-id", "A1")).then_return( + inner_well_def + ) + ten_ul_height = subject.get_well_height_at_volume( + labware_id="labware-id", well_name="A1", volume=10.0 + ) + twenty_ul_height = subject.get_well_height_at_volume( + labware_id="labware-id", well_name="A1", volume=20.0 + ) + + # Make sure Get height with no information raises an error + decoy.when(mock_well_view.get_last_liquid_update("labware-id", "A1")).then_return( + None + ) + decoy.when(mock_well_view.get_well_liquid_info("labware-id", "A1")).then_return( + WellLiquidInfo( + loaded_volume=None, + probed_height=None, + probed_volume=None, + ) + ) + decoy.when(mock_well_view.get_last_liquid_update("labware-id", "A1")).then_return( + None + ) + + with pytest.raises(errors.LiquidHeightUnknownError): + subject.get_meniscus_height(labware_id="labware-id", well_name="A1") + # Make sure get height with a valid load returns the correct height + decoy.when(mock_well_view.get_well_liquid_info("labware-id", "A1")).then_return( + WellLiquidInfo( + loaded_volume=LoadedVolumeInfo( + volume=10.0, last_loaded=load_time, operations_since_load=0 + ), + probed_height=None, + probed_volume=None, + ) + ) + + decoy.when(mock_well_view.get_last_liquid_update("labware-id", "A1")).then_return( + load_time + ) + assert ( + subject.get_meniscus_height(labware_id="labware-id", well_name="A1") + == ten_ul_height + ) + + # Make sure that if there is a probe after a load that we get the correct height + decoy.when(mock_well_view.get_well_liquid_info("labware-id", "A1")).then_return( + WellLiquidInfo( + loaded_volume=LoadedVolumeInfo( + volume=10.0, last_loaded=load_time, operations_since_load=0 + ), + probed_height=ProbedHeightInfo(height=40.0, last_probed=probe_time), + probed_volume=None, + ) + ) + decoy.when(mock_well_view.get_last_liquid_update("labware-id", "A1")).then_return( + probe_time + ) + + assert subject.get_meniscus_height(labware_id="labware-id", well_name="A1") == 40.0 + + # Simulate a pipetting action and make sure we get the height based on the most current one + decoy.when(mock_well_view.get_well_liquid_info("labware-id", "A1")).then_return( + WellLiquidInfo( + loaded_volume=LoadedVolumeInfo( + volume=10.0, last_loaded=load_time, operations_since_load=1 + ), + probed_height=None, + probed_volume=ProbedVolumeInfo( + volume=20.0, last_probed=probe_time, operations_since_probe=1 + ), + ) + ) + decoy.when(mock_well_view.get_last_liquid_update("labware-id", "A1")).then_return( + probe_time + ) + assert ( + subject.get_meniscus_height(labware_id="labware-id", well_name="A1") + == twenty_ul_height + ) + + # Simulate a calling load_liquid after a probe and make sure we get the height based on the load_liquid + decoy.when(mock_well_view.get_well_liquid_info("labware-id", "A1")).then_return( + WellLiquidInfo( + loaded_volume=LoadedVolumeInfo( + volume=10.0, last_loaded=datetime.max, operations_since_load=0 + ), + probed_height=ProbedHeightInfo(height=40.0, last_probed=probe_time), + probed_volume=ProbedVolumeInfo( + volume=20.0, last_probed=probe_time, operations_since_probe=0 + ), + ) + ) + decoy.when(mock_well_view.get_last_liquid_update("labware-id", "A1")).then_return( + datetime.max + ) + assert ( + subject.get_meniscus_height(labware_id="labware-id", well_name="A1") + == ten_ul_height + ) + + @pytest.mark.parametrize( [ "labware_id", From 16bd893b30dbaf1ffb3d46fc258f1f0966b94867 Mon Sep 17 00:00:00 2001 From: Jethary Alcid <66035149+jerader@users.noreply.github.com> Date: Wed, 29 Jan 2025 12:50:46 -0500 Subject: [PATCH 16/22] feat(protocol-designer): timeline scrubber to the overview page (#17301) Some skunkwork that adds the timeline scrubber to PD's overview behind a feature flag. --- .../ProtocolDetails/ProtocolTimeline.tsx | 6 +- .../ProtocolTimelineScrubber/index.tsx | 47 +++-- .../ProtocolTimelineScrubber/utils.ts | 8 +- .../assets/localization/en/feature_flags.json | 4 + .../src/assets/localization/en/index.ts | 2 + .../en/protocol_command_text.json | 100 +++++++++ .../src/feature-flags/reducers.ts | 2 + .../src/feature-flags/selectors.ts | 4 + protocol-designer/src/feature-flags/types.ts | 2 + .../src/file-data/selectors/fileCreator.ts | 183 +--------------- .../src/file-data/selectors/utils.ts | 195 ++++++++++++++++++ .../ProtocolOverview/ScrubberContainer.tsx | 172 +++++++++++++++ .../src/pages/ProtocolOverview/index.tsx | 5 +- .../utils/createTimelineFromRunCommands.ts | 6 +- step-generation/src/utils/index.ts | 2 + 15 files changed, 529 insertions(+), 209 deletions(-) create mode 100644 protocol-designer/src/assets/localization/en/protocol_command_text.json create mode 100644 protocol-designer/src/file-data/selectors/utils.ts create mode 100644 protocol-designer/src/pages/ProtocolOverview/ScrubberContainer.tsx diff --git a/app/src/pages/Desktop/Protocols/ProtocolDetails/ProtocolTimeline.tsx b/app/src/pages/Desktop/Protocols/ProtocolDetails/ProtocolTimeline.tsx index cb316e5e734..9651dcbc477 100644 --- a/app/src/pages/Desktop/Protocols/ProtocolDetails/ProtocolTimeline.tsx +++ b/app/src/pages/Desktop/Protocols/ProtocolDetails/ProtocolTimeline.tsx @@ -27,11 +27,7 @@ export function ProtocolTimeline(): JSX.Element { return storedProtocol != null && storedProtocol.mostRecentAnalysis != null ? ( - + ) : ( diff --git a/components/src/organisms/ProtocolTimelineScrubber/index.tsx b/components/src/organisms/ProtocolTimelineScrubber/index.tsx index ffcd328dd48..845103786c1 100644 --- a/components/src/organisms/ProtocolTimelineScrubber/index.tsx +++ b/components/src/organisms/ProtocolTimelineScrubber/index.tsx @@ -3,7 +3,10 @@ import map from 'lodash/map' import reduce from 'lodash/reduce' import ViewportList from 'react-viewport-list' -import { getResultingTimelineFrameFromRunCommands } from '@opentrons/step-generation' +import { + constructInvariantContextFromRunCommands, + getResultingTimelineFrameFromRunCommands, +} from '@opentrons/step-generation' import { FLEX_ROBOT_TYPE, THERMOCYCLER_MODULE_TYPE, @@ -36,11 +39,10 @@ import type { CompletedProtocolAnalysis, LabwareLocation, ProtocolAnalysisOutput, - RobotType, - RunTimeCommand, } from '@opentrons/shared-data' import type { ModuleTemporalProperties } from '@opentrons/step-generation' import type { LabwareOnDeck, Module } from '../..' + export * from './types' export * from './utils' @@ -48,9 +50,8 @@ const SEC_PER_FRAME = 1000 export const COMMAND_WIDTH_PX = 240 interface ProtocolTimelineScrubberProps { - commands: RunTimeCommand[] analysis: CompletedProtocolAnalysis | ProtocolAnalysisOutput - robotType?: RobotType + height?: string } export const DECK_LAYER_BLOCKLIST = [ @@ -62,23 +63,24 @@ export const DECK_LAYER_BLOCKLIST = [ 'removableDeckOutline', 'screwHoles', ] -export const VIEWBOX_MIN_X = -84 -export const VIEWBOX_MIN_Y = -10 -export const VIEWBOX_WIDTH = 600 -export const VIEWBOX_HEIGHT = 460 export function ProtocolTimelineScrubber( props: ProtocolTimelineScrubberProps ): JSX.Element { - const { commands, analysis, robotType = FLEX_ROBOT_TYPE } = props + const { analysis, height } = props + const { commands, robotType, liquids } = analysis const wrapperRef = useRef(null) const commandListRef = useRef(null) const [currentCommandIndex, setCurrentCommandIndex] = useState(0) const [isPlaying, setIsPlaying] = useState(true) const currentCommandsSlice = commands.slice(0, currentCommandIndex + 1) + const invariantContextFromRunCommands = constructInvariantContextFromRunCommands( + commands + ) const { frame, invariantContext } = getResultingTimelineFrameFromRunCommands( - currentCommandsSlice + currentCommandsSlice, + invariantContextFromRunCommands ) const handlePlayPause = (): void => { setIsPlaying(!isPlaying) @@ -120,31 +122,28 @@ export function ProtocolTimelineScrubber( const allWellContentsForActiveItem = getAllWellContentsForActiveItem( invariantContext.labwareEntities, - frame + robotState ) - const liquidDisplayColors = analysis.liquids.map( - liquid => liquid.displayColor ?? COLORS.blue50 + const liquidDisplayColors = liquids.map( + ({ displayColor }) => displayColor ?? COLORS.blue50 ) const isValidRobotSideAnalysis = analysis != null const allRunDefs = useMemo( - () => - analysis != null - ? getLabwareDefinitionsFromCommands(analysis.commands) - : [], + () => getLabwareDefinitionsFromCommands(commands), [isValidRobotSideAnalysis] ) return ( - + { const labwareInModuleId = @@ -263,14 +262,14 @@ export function ProtocolTimelineScrubber( mount="left" pipetteId={leftPipetteId} pipetteEntity={leftPipetteEntity} - timelineFrame={frame.robotState} + timelineFrame={robotState} analysis={analysis} /> @@ -293,7 +292,7 @@ export function ProtocolTimelineScrubber( currentCommandIndex={currentCommandIndex} setCurrentCommandIndex={setCurrentCommandIndex} analysis={analysis} - robotType={robotType} + robotType={robotType ?? FLEX_ROBOT_TYPE} allRunDefs={allRunDefs} /> )} diff --git a/components/src/organisms/ProtocolTimelineScrubber/utils.ts b/components/src/organisms/ProtocolTimelineScrubber/utils.ts index 531cdf86976..44b48e30bc4 100644 --- a/components/src/organisms/ProtocolTimelineScrubber/utils.ts +++ b/components/src/organisms/ProtocolTimelineScrubber/utils.ts @@ -13,8 +13,8 @@ import type { import type { LabwareEntities, LocationLiquidState, - RunCommandTimelineFrame, SingleLabwareLiquidState, + TimelineFrame, } from '@opentrons/step-generation' import type { CommandTextData } from './types' @@ -127,11 +127,11 @@ export const wellFillFromWellContents = ( export function getAllWellContentsForActiveItem( labwareEntities: LabwareEntities, - timelineFrame: RunCommandTimelineFrame + robotState: TimelineFrame ): WellContentsByLabware | null { - if (timelineFrame == null) return null + if (robotState == null) return null - const liquidState = timelineFrame.robotState.liquidState.labware + const liquidState = robotState.liquidState.labware const wellContentsByLabwareId = mapValues( liquidState, (labwareLiquids: SingleLabwareLiquidState, labwareId: string) => { diff --git a/protocol-designer/src/assets/localization/en/feature_flags.json b/protocol-designer/src/assets/localization/en/feature_flags.json index 851f8deb5a9..d2077d224ea 100644 --- a/protocol-designer/src/assets/localization/en/feature_flags.json +++ b/protocol-designer/src/assets/localization/en/feature_flags.json @@ -31,5 +31,9 @@ "OT_PD_ENABLE_LIQUID_CLASSES": { "title": "Enable liquid classes", "description": "Enable liquid classes support" + }, + "OT_PD_ENABLE_TIMELINE_SCRUBBER": { + "title": "Enable timeline scrubber", + "description": "See the protocol timeline visualization in overview" } } diff --git a/protocol-designer/src/assets/localization/en/index.ts b/protocol-designer/src/assets/localization/en/index.ts index 68ed9877a8e..7cb72b02f54 100644 --- a/protocol-designer/src/assets/localization/en/index.ts +++ b/protocol-designer/src/assets/localization/en/index.ts @@ -11,6 +11,7 @@ import liquids from './liquids.json' import modal from './modal.json' import modules from './modules.json' import nav from './nav.json' +import protocol_command_text from './protocol_command_text.json' import protocol_overview from './protocol_overview.json' import protocol_steps from './protocol_steps.json' import shared from './shared.json' @@ -32,6 +33,7 @@ export const en = { modal, modules, nav, + protocol_command_text, protocol_overview, protocol_steps, shared, diff --git a/protocol-designer/src/assets/localization/en/protocol_command_text.json b/protocol-designer/src/assets/localization/en/protocol_command_text.json new file mode 100644 index 00000000000..8037b8f2778 --- /dev/null +++ b/protocol-designer/src/assets/localization/en/protocol_command_text.json @@ -0,0 +1,100 @@ +{ + "absorbance_reader_close_lid": "Closing Absorbance Reader lid", + "absorbance_reader_initialize": "Initializing Absorbance Reader to perform {{mode}} measurement at {{wavelengths}}", + "absorbance_reader_open_lid": "Opening Absorbance Reader lid", + "absorbance_reader_read": "Reading plate in Absorbance Reader", + "adapter_in_mod_in_slot": "{{adapter}} on {{module}} in Slot {{slot}}", + "adapter_in_slot": "{{adapter}} in Slot {{slot}}", + "air_gap_in_place": "Air gapping {{volume}} µL", + "all_nozzles": "all nozzles", + "aspirate": "Aspirating {{volume}} µL from well {{well_name}} of {{labware}} in {{labware_location}} at {{flow_rate}} µL/sec", + "aspirate_in_place": "Aspirating {{volume}} µL in place at {{flow_rate}} µL/sec ", + "blowout": "Blowing out at well {{well_name}} of {{labware}} in {{labware_location}} at {{flow_rate}} µL/sec", + "blowout_in_place": "Blowing out in place at {{flow_rate}} µL/sec", + "closing_tc_lid": "Closing Thermocycler lid", + "column_layout": "column layout", + "comment": "Comment", + "configure_for_volume": "Configure {{pipette}} to aspirate {{volume}} µL", + "configure_nozzle_layout": "Configure {{pipette}} to use {{layout}}", + "confirm_and_resume": "Confirm and resume", + "deactivate_hs_shake": "Deactivating shaker", + "deactivate_temperature_module": "Deactivating Temperature Module", + "deactivating_hs_heater": "Deactivating heater", + "deactivating_tc_block": "Deactivating Thermocycler block", + "deactivating_tc_lid": "Deactivating Thermocycler lid", + "degrees_c": "{{temp}}°C", + "detect_liquid_presence": "Detecting liquid presence in well {{well_name}} of {{labware}} in {{labware_location}}", + "disengaging_magnetic_module": "Disengaging Magnetic Module", + "dispense": "Dispensing {{volume}} µL into well {{well_name}} of {{labware}} in {{labware_location}} at {{flow_rate}} µL/sec", + "dispense_in_place": "Dispensing {{volume}} µL in place at {{flow_rate}} µL/sec", + "dispense_push_out": "Dispensing {{volume}} µL into well {{well_name}} of {{labware}} in {{labware_location}} at {{flow_rate}} µL/sec and pushing out {{push_out_volume}} µL", + "drop_tip": "Dropping tip in {{well_name}} of {{labware}}", + "drop_tip_in_place": "Dropping tip in place", + "dropping_tip_in_trash": "Dropping tip in {{trash}}", + "engaging_magnetic_module": "Engaging Magnetic Module", + "fixed_trash": "Fixed Trash", + "home_gantry": "Homing all gantry, pipette, and plunger axes", + "in_location": "in {{location}}", + "latching_hs_latch": "Latching labware on Heater-Shaker", + "left": "Left", + "load_labware_to_display_location": "Load {{labware}} {{display_location}}", + "load_liquids_info_protocol_setup": "Load {{liquid}} into {{labware}}", + "load_module_protocol_setup": "Load {{module}} in Slot {{slot_name}}", + "load_pipette_protocol_setup": "Load {{pipette_name}} in {{mount_name}} Mount", + "module_in_slot": "{{module}} in Slot {{slot_name}}", + "module_in_slot_plural": "{{module}}", + "move_labware": "Move Labware", + "move_labware_manually": "Manually move {{labware}} from {{old_location}} to {{new_location}}", + "move_labware_on": "Move labware on {{robot_name}}", + "move_labware_using_gripper": "Moving {{labware}} using gripper from {{old_location}} to {{new_location}}", + "move_relative": "Moving {{distance}} mm along {{axis}} axis", + "move_to_addressable_area": "Moving to {{addressable_area}}", + "move_to_addressable_area_drop_tip": "Moving to {{addressable_area}}", + "move_to_coordinates": "Moving to (X: {{x}}, Y: {{y}}, Z: {{z}})", + "move_to_slot": "Moving to Slot {{slot_name}}", + "move_to_well": "Moving to well {{well_name}} of {{labware}} in {{labware_location}}", + "multiple": "multiple", + "notes": "notes", + "off_deck": "off deck", + "offdeck": "offdeck", + "on_location": "on {{location}}", + "opening_tc_lid": "Opening Thermocycler lid", + "pause": "Pause", + "pause_on": "Pause on {{robot_name}}", + "partial_layout": "partial layout", + "pickup_tip": "Picking up tip(s) from {{well_range}} of {{labware}} in {{labware_location}}", + "prepare_to_aspirate": "Preparing {{pipette}} to aspirate", + "reloading_labware": "Reloading {{labware}}", + "return_tip": "Returning tip to {{well_name}} of {{labware}} in {{labware_location}}", + "right": "Right", + "row_layout": "row layout", + "save_position": "Saving position", + "set_and_await_hs_shake": "Setting Heater-Shaker to shake at {{rpm}} rpm and waiting until reached", + "setting_hs_temp": "Setting Target Temperature of Heater-Shaker to {{temp}}", + "setting_temperature_module_temp": "Setting Temperature Module to {{temp}} (rounded to nearest integer)", + "setting_thermocycler_block_temp": "Setting Thermocycler block temperature to {{temp}} with hold time of {{hold_time_seconds}} seconds after target reached", + "setting_thermocycler_lid_temp": "Setting Thermocycler lid temperature to {{temp}}", + "single": "single", + "single_nozzle_layout": "single nozzle layout", + "slot": "Slot {{slot_name}}", + "target_temperature": "target temperature", + "tc_awaiting_for_duration": "Waiting for Thermocycler profile to complete", + "tc_run_profile_steps": "Temperature: {{celsius}}°C, hold time: {{duration}}", + "tc_starting_extended_profile": "Running thermocycler profile with {{elementCount}} total steps and cycles:", + "tc_starting_extended_profile_cycle": "{{repetitions}} repetitions of the following steps:", + "tc_starting_profile": "Running thermocycler profile with {{stepCount}} steps:", + "touch_tip": "Touching tip", + "trash_bin": "Trash Bin", + "trash_bin_in_slot": "Trash Bin in {{slot_name}}", + "turning_rail_lights_off": "Turning rail lights off", + "turning_rail_lights_on": "Turning rail lights on", + "unlatching_hs_latch": "Unlatching labware on Heater-Shaker", + "wait_for_duration": "Pausing for {{seconds}} seconds. {{message}}", + "wait_for_resume": "Pausing protocol", + "waiting_for_hs_to_reach": "Waiting for Heater-Shaker to reach target temperature", + "waiting_for_tc_block_to_reach": "Waiting for Thermocycler block to reach target temperature and holding for specified time", + "waiting_for_tc_lid_to_reach": "Waiting for Thermocycler lid to reach target temperature", + "waiting_to_reach_temp_module": "Waiting for Temperature Module to reach {{temp}}", + "waste_chute": "Waste Chute", + "with_reference_of": "with reference of {{wavelength}} nm" +} diff --git a/protocol-designer/src/feature-flags/reducers.ts b/protocol-designer/src/feature-flags/reducers.ts index efec2f863dd..8760d08c3ea 100644 --- a/protocol-designer/src/feature-flags/reducers.ts +++ b/protocol-designer/src/feature-flags/reducers.ts @@ -30,6 +30,8 @@ const initialFlags: Flags = { OT_PD_ENABLE_REACT_SCAN: process.env.OT_PD_ENABLE_REACT_SCAN === '1' || false, OT_PD_ENABLE_LIQUID_CLASSES: process.env.OT_PD_ENABLE_LIQUID_CLASSES === '1' || false, + OT_PD_ENABLE_TIMELINE_SCRUBBER: + process.env.OT_PD_ENABLE_TIMELINE_SCRUBBER === '1' || false, } // @ts-expect-error(sa, 2021-6-10): cannot use string literals as action type // TODO IMMEDIATELY: refactor this to the old fashioned way if we cannot have type safety: https://github.com/redux-utilities/redux-actions/issues/282#issuecomment-595163081 diff --git a/protocol-designer/src/feature-flags/selectors.ts b/protocol-designer/src/feature-flags/selectors.ts index d673ad6bf09..9cc722d5388 100644 --- a/protocol-designer/src/feature-flags/selectors.ts +++ b/protocol-designer/src/feature-flags/selectors.ts @@ -45,3 +45,7 @@ export const getEnableLiquidClasses: Selector = createSelector( getFeatureFlagData, flags => flags.OT_PD_ENABLE_LIQUID_CLASSES ?? false ) +export const getEnableTimelineScrubber: Selector = createSelector( + getFeatureFlagData, + flags => flags.OT_PD_ENABLE_TIMELINE_SCRUBBER ?? false +) diff --git a/protocol-designer/src/feature-flags/types.ts b/protocol-designer/src/feature-flags/types.ts index 53ea6615c8b..20dcbaa8d5e 100644 --- a/protocol-designer/src/feature-flags/types.ts +++ b/protocol-designer/src/feature-flags/types.ts @@ -37,6 +37,7 @@ export type FlagTypes = | 'OT_PD_ENABLE_HOT_KEYS_DISPLAY' | 'OT_PD_ENABLE_REACT_SCAN' | 'OT_PD_ENABLE_LIQUID_CLASSES' + | 'OT_PD_ENABLE_TIMELINE_SCRUBBER' // flags that are not in this list only show in prerelease mode export const userFacingFlags: FlagTypes[] = [ 'OT_PD_DISABLE_MODULE_RESTRICTIONS', @@ -50,5 +51,6 @@ export const allFlags: FlagTypes[] = [ 'OT_PD_ENABLE_RETURN_TIP', 'OT_PD_ENABLE_REACT_SCAN', 'OT_PD_ENABLE_LIQUID_CLASSES', + 'OT_PD_ENABLE_TIMELINE_SCRUBBER', ] export type Flags = Partial> diff --git a/protocol-designer/src/file-data/selectors/fileCreator.ts b/protocol-designer/src/file-data/selectors/fileCreator.ts index cea1d6022be..8ae0e1b560a 100644 --- a/protocol-designer/src/file-data/selectors/fileCreator.ts +++ b/protocol-designer/src/file-data/selectors/fileCreator.ts @@ -2,7 +2,6 @@ import { createSelector } from 'reselect' import flatMap from 'lodash/flatMap' import isEmpty from 'lodash/isEmpty' import mapValues from 'lodash/mapValues' -import map from 'lodash/map' import reduce from 'lodash/reduce' import uniq from 'lodash/uniq' import { @@ -10,18 +9,14 @@ import { OT2_STANDARD_DECKID, OT2_STANDARD_MODEL, FLEX_STANDARD_DECKID, - SPAN7_8_10_11_SLOT, } from '@opentrons/shared-data' -import { COLUMN_4_SLOTS } from '@opentrons/step-generation' import { selectors as dismissSelectors } from '../../dismiss' import { selectors as labwareDefSelectors } from '../../labware-defs' -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 { swatchColors } from '../../organisms/DefineLiquidsModal/swatchColors' -import { getLoadLiquidCommands } from '../../load-file/migration/utils/getLoadLiquidCommands' import { DEFAULT_MM_TOUCH_TIP_OFFSET_FROM_TOP, DEFAULT_MM_BLOWOUT_OFFSET_FROM_TOP, @@ -30,27 +25,21 @@ import { import { getStepGroups } from '../../step-forms/selectors' import { getFileMetadata, getRobotType } from './fileFields' import { getInitialRobotState, getRobotStateTimeline } from './commands' +import { getLoadCommands } from './utils' import type { PipetteEntity, LabwareEntities, PipetteEntities, - RobotState, } from '@opentrons/step-generation' import type { - LabwareLocation, - AddressableAreaName, CommandAnnotationV1Mixin, CommandV8Mixin, CreateCommand, LabwareV2Mixin, LiquidV1Mixin, - LoadLabwareCreateCommand, - LoadModuleCreateCommand, - LoadPipetteCreateCommand, OT2RobotMixin, OT3RobotMixin, - PipetteName, ProtocolBase, ProtocolFile, } from '@opentrons/shared-data' @@ -132,6 +121,16 @@ export const createFile: Selector = createSelector( ) => { const { author, description, created } = fileMetadata + const loadCommands = getLoadCommands( + initialRobotState, + pipetteEntities, + moduleEntities, + labwareEntities, + labwareNicknamesById, + ingredients, + ingredLocations + ) + 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 @@ -167,39 +166,6 @@ export const createFile: Selector = createSelector( }, } - interface Pipettes { - [pipetteId: string]: { name: PipetteName } - } - - const pipettes: Pipettes = mapValues( - initialRobotState.pipettes, - ( - pipette: typeof initialRobotState.pipettes[keyof typeof initialRobotState.pipettes], - pipetteId: string - ) => ({ - name: pipetteEntities[pipetteId].name, - }) - ) - - const loadPipetteCommands = map( - initialRobotState.pipettes, - ( - pipette: typeof initialRobotState.pipettes[keyof typeof initialRobotState.pipettes], - pipetteId: string - ): LoadPipetteCreateCommand => { - const loadPipetteCommand = { - key: uuid(), - commandType: 'loadPipette' as const, - params: { - pipetteName: pipettes[pipetteId].name, - mount: pipette.mount, - pipetteId: pipetteId, - }, - } - return loadPipetteCommand - } - ) - const liquids: ProtocolFile['liquids'] = reduce( ingredients, (acc, liquidData, liquidId) => { @@ -214,139 +180,12 @@ export const createFile: Selector = createSelector( }, {} ) - // initiate "adapter" commands first so we can map through them to get the - // labware that goes on top of it's location - const loadAdapterCommands = reduce< - RobotState['labware'], - LoadLabwareCreateCommand[] - >( - initialRobotState.labware, - ( - acc, - labware: typeof initialRobotState.labware[keyof typeof initialRobotState.labware], - labwareId: string - ): LoadLabwareCreateCommand[] => { - const { def } = labwareEntities[labwareId] - const isAdapter = def.allowedRoles?.includes('adapter') - if (!isAdapter) return acc - const isOnTopOfModule = labware.slot in initialRobotState.modules - const namespace = def.namespace - const loadName = def.parameters.loadName - const version = def.version - const loadAdapterCommands = { - key: uuid(), - commandType: 'loadLabware' as const, - params: { - displayName: def.metadata.displayName, - labwareId, - loadName, - namespace: namespace, - version: version, - location: isOnTopOfModule - ? { moduleId: labware.slot } - : { slotName: labware.slot }, - }, - } - - return [...acc, loadAdapterCommands] - }, - [] - ) - - const loadLabwareCommands = reduce< - RobotState['labware'], - LoadLabwareCreateCommand[] - >( - initialRobotState.labware, - ( - acc, - labware: typeof initialRobotState.labware[keyof typeof initialRobotState.labware], - labwareId: string - ): LoadLabwareCreateCommand[] => { - const { def } = labwareEntities[labwareId] - const isAdapter = def.allowedRoles?.includes('adapter') - if (isAdapter || def.metadata.displayCategory === 'trash') return acc - const isOnTopOfModule = labware.slot in initialRobotState.modules - const isOnAdapter = - loadAdapterCommands.find( - command => command.params.labwareId === labware.slot - ) != null - const namespace = def.namespace - const loadName = def.parameters.loadName - const version = def.version - const isAddressableAreaName = COLUMN_4_SLOTS.includes(labware.slot) - - let location: LabwareLocation = { slotName: labware.slot } - if (isOnTopOfModule) { - location = { moduleId: labware.slot } - } else if (isOnAdapter) { - location = { labwareId: labware.slot } - } else if (isAddressableAreaName) { - // TODO(bh, 2024-01-02): check slots against addressable areas via the deck definition - location = { - addressableAreaName: labware.slot as AddressableAreaName, - } - } else if (labware.slot === 'offDeck') { - location = 'offDeck' - } - - const loadLabwareCommands = { - key: uuid(), - commandType: 'loadLabware' as const, - params: { - displayName: - labwareNicknamesById[labwareId] ?? def.metadata.displayName, - labwareId: labwareId, - loadName, - namespace: namespace, - version: version, - location, - }, - } - - return [...acc, loadLabwareCommands] - }, - [] - ) - - const loadLiquidCommands = getLoadLiquidCommands( - ingredients, - ingredLocations - ) - const loadModuleCommands = map( - initialRobotState.modules, - ( - module: typeof initialRobotState.modules[keyof typeof initialRobotState.modules], - moduleId: string - ): LoadModuleCreateCommand => { - const model = moduleEntities[moduleId].model - const loadModuleCommand = { - key: uuid(), - commandType: 'loadModule' as const, - params: { - model: model, - location: { - slotName: module.slot === SPAN7_8_10_11_SLOT ? '7' : module.slot, - }, - moduleId: moduleId, - }, - } - return loadModuleCommand - } - ) const labwareDefinitions = getLabwareDefinitionsInUse( labwareEntities, pipetteEntities, labwareDefsByURI ) - const loadCommands: CreateCommand[] = [ - ...loadPipetteCommands, - ...loadModuleCommands, - ...loadAdapterCommands, - ...loadLabwareCommands, - ...loadLiquidCommands, - ] const nonLoadCommands: CreateCommand[] = flatMap( robotStateTimeline.timeline, diff --git a/protocol-designer/src/file-data/selectors/utils.ts b/protocol-designer/src/file-data/selectors/utils.ts new file mode 100644 index 00000000000..57a8ba89947 --- /dev/null +++ b/protocol-designer/src/file-data/selectors/utils.ts @@ -0,0 +1,195 @@ +import mapValues from 'lodash/mapValues' +import map from 'lodash/map' +import reduce from 'lodash/reduce' +import { getLoadLiquidCommands } from '../../load-file/migration/utils/getLoadLiquidCommands' +import { COLUMN_4_SLOTS, uuid } from '@opentrons/step-generation' + +import type { + AddressableAreaName, + CreateCommand, + LabwareLocation, + LoadLabwareCreateCommand, + LoadModuleCreateCommand, + LoadPipetteCreateCommand, + PipetteName, +} from '@opentrons/shared-data' +import type { + LabwareEntities, + LabwareLiquidState, + PipetteEntities, + RobotState, + ModuleEntities, + TimelineFrame, +} from '@opentrons/step-generation' +import type { LiquidGroupsById } from '../../labware-ingred/types' + +interface Pipettes { + [pipetteId: string]: { name: PipetteName } +} + +export const getLoadCommands = ( + initialRobotState: TimelineFrame, + pipetteEntities: PipetteEntities, + moduleEntities: ModuleEntities, + labwareEntities: LabwareEntities, + labwareNicknamesById: Record, + ingredients: LiquidGroupsById, + ingredLocations: LabwareLiquidState +): CreateCommand[] => { + const pipettes: Pipettes = mapValues( + initialRobotState.pipettes, + ( + pipette: typeof initialRobotState.pipettes[keyof typeof initialRobotState.pipettes], + pipetteId: string + ) => ({ + name: pipetteEntities[pipetteId].name, + }) + ) + + const loadPipetteCommands = map( + initialRobotState.pipettes, + ( + pipette: typeof initialRobotState.pipettes[keyof typeof initialRobotState.pipettes], + pipetteId: string + ): LoadPipetteCreateCommand => { + const loadPipetteCommand = { + key: uuid(), + commandType: 'loadPipette' as const, + params: { + pipetteName: pipettes[pipetteId].name, + mount: pipette.mount, + pipetteId: pipetteId, + }, + } + return loadPipetteCommand + } + ) + + // initiate "adapter" commands first so we can map through them to get the + // labware that goes on top of it's location + const loadAdapterCommands = reduce< + RobotState['labware'], + LoadLabwareCreateCommand[] + >( + initialRobotState.labware, + ( + acc, + labware: typeof initialRobotState.labware[keyof typeof initialRobotState.labware], + labwareId: string + ): LoadLabwareCreateCommand[] => { + const { def } = labwareEntities[labwareId] + const isAdapter = def.allowedRoles?.includes('adapter') + if (!isAdapter) { + return acc + } + const isOnTopOfModule = labware.slot in initialRobotState.modules + const { namespace, parameters, version, metadata } = def + const loadName = parameters.loadName + const loadAdapterCommands = { + key: uuid(), + commandType: 'loadLabware' as const, + params: { + displayName: metadata.displayName, + labwareId, + loadName, + namespace, + version, + location: isOnTopOfModule + ? { moduleId: labware.slot } + : { slotName: labware.slot }, + }, + } + + return [...acc, loadAdapterCommands] + }, + [] + ) + + const loadLabwareCommands = reduce< + RobotState['labware'], + LoadLabwareCreateCommand[] + >( + initialRobotState.labware, + ( + acc, + labware: typeof initialRobotState.labware[keyof typeof initialRobotState.labware], + labwareId: string + ): LoadLabwareCreateCommand[] => { + const { def } = labwareEntities[labwareId] + const isAdapter = def.allowedRoles?.includes('adapter') + if (isAdapter || def.metadata.displayCategory === 'trash') return acc + const isOnTopOfModule = labware.slot in initialRobotState.modules + const isOnAdapter = + loadAdapterCommands.find( + command => command.params.labwareId === labware.slot + ) != null + const { namespace, parameters, version } = def + const loadName = parameters.loadName + + const isAddressableAreaName = COLUMN_4_SLOTS.includes(labware.slot) + + let location: LabwareLocation = { slotName: labware.slot } + if (isOnTopOfModule) { + location = { moduleId: labware.slot } + } else if (isOnAdapter) { + location = { labwareId: labware.slot } + } else if (isAddressableAreaName) { + // TODO(bh, 2024-01-02): check slots against addressable areas via the deck definition + location = { + addressableAreaName: labware.slot as AddressableAreaName, + } + } else if (labware.slot === 'offDeck') { + location = 'offDeck' + } + + const loadLabwareCommands = { + key: uuid(), + commandType: 'loadLabware' as const, + params: { + displayName: + labwareNicknamesById[labwareId] ?? def.metadata.displayName, + labwareId: labwareId, + loadName, + namespace: namespace, + version: version, + location, + }, + } + + return [...acc, loadLabwareCommands] + }, + [] + ) + + const loadLiquidCommands = getLoadLiquidCommands(ingredients, ingredLocations) + + const loadModuleCommands = map( + initialRobotState.modules, + ( + module: typeof initialRobotState.modules[keyof typeof initialRobotState.modules], + moduleId: string + ): LoadModuleCreateCommand => { + const model = moduleEntities[moduleId].model + const loadModuleCommand = { + key: uuid(), + commandType: 'loadModule' as const, + params: { + model: model, + location: { + slotName: module.slot, + }, + moduleId: moduleId, + }, + } + return loadModuleCommand + } + ) + + return [ + ...loadPipetteCommands, + ...loadModuleCommands, + ...loadAdapterCommands, + ...loadLabwareCommands, + ...loadLiquidCommands, + ] +} diff --git a/protocol-designer/src/pages/ProtocolOverview/ScrubberContainer.tsx b/protocol-designer/src/pages/ProtocolOverview/ScrubberContainer.tsx new file mode 100644 index 00000000000..52151876a61 --- /dev/null +++ b/protocol-designer/src/pages/ProtocolOverview/ScrubberContainer.tsx @@ -0,0 +1,172 @@ +import { useSelector } from 'react-redux' +import flatMap from 'lodash/flatMap' +import { ProtocolTimelineScrubber } from '@opentrons/components' +import { OT2_ROBOT_TYPE } from '@opentrons/shared-data' +import { + getInitialRobotState, + getRobotStateTimeline, + getRobotType, +} from '../../file-data/selectors' +import { uuid } from '../../utils' +import { + getInitialDeckSetup, + getInvariantContext, +} from '../../step-forms/selectors' +import { getLabwareNicknamesById } from '../../ui/labware/selectors' +import { selectors as ingredSelectors } from '../../labware-ingred/selectors' +import { getLoadCommands } from '../../file-data/selectors/utils' +import type { + AddressableAreaName, + CompletedProtocolAnalysis, + LabwareLocation, + Liquid, + LoadModuleRunTimeCommand, + LoadedLabware, + LoadedModule, + LoadedPipette, + RunTimeCommand, +} from '@opentrons/shared-data' + +export function ScrubberContainer(): JSX.Element | null { + const robotType = useSelector(getRobotType) + const labwareNickNames = useSelector(getLabwareNicknamesById) + const robotStateTimeline = useSelector(getRobotStateTimeline) + const initialRobotState = useSelector(getInitialRobotState) + const ingredients = useSelector(ingredSelectors.getLiquidGroupsById) + const ingredientLocations = useSelector(ingredSelectors.getLiquidsByLabwareId) + const invariantContext = useSelector(getInvariantContext) + const initialDeckSetup = useSelector(getInitialDeckSetup) + + if (robotType === OT2_ROBOT_TYPE) { + return null + } + + const { pipetteEntities, labwareEntities, moduleEntities } = invariantContext + const { + pipettes, + modules, + labware, + additionalEquipmentOnDeck, + } = initialDeckSetup + + const loadCommands = getLoadCommands( + initialRobotState, + pipetteEntities, + moduleEntities, + labwareEntities, + labwareNickNames, + ingredients, + ingredientLocations + ) + const nonLoadCommands = flatMap( + robotStateTimeline.timeline, + timelineFrame => timelineFrame.commands + ) + const runTimeCommands: RunTimeCommand[] = [ + ...loadCommands, + ...nonLoadCommands, + ].map(command => { + let result + if (command.commandType === 'loadModule') { + const loadModuleResult: LoadModuleRunTimeCommand['result'] = { + moduleId: command.params.moduleId ?? '', + } + result = loadModuleResult + } else if (command.commandType === 'loadLabware') { + result = { + labwareId: command.params.labwareId, + definition: labwareEntities[command.params.labwareId ?? '']?.def, + } + } else if (command.commandType === 'loadPipette') { + result = { + pipetteId: command.params.pipetteId, + } + } + // @ts-expect-error: TS angry because not all commands have a result but + // results are added to only commands that need them for the scrubber + const runTimeCommand: RunTimeCommand = { + ...command, + id: uuid(), + status: 'succeeded', + createdAt: '', + startedAt: '', + completedAt: '', + result, + } + return runTimeCommand + }) + + const loadPipettes: LoadedPipette[] = Object.values(pipettes).map( + pipette => ({ + id: pipette.id, + pipetteName: pipette.name, + mount: pipette.mount, + }) + ) + const loadModules: LoadedModule[] = Object.values(modules).map(module => ({ + id: module.id, + model: module.model, + serialNumber: '1', // TODO: why? seems like we don't need it for command text though + location: { + slotName: module.slot, + }, + })) + + const loadLabware: LoadedLabware[] = Object.values(labware).map(lw => { + let location: LabwareLocation = { slotName: lw.slot } + if (lw.slot in modules) { + location = { moduleId: lw.slot } + } else if ( + labware[lw.slot] != null && + labware[lw.slot].def.allowedRoles?.includes('adapter') + ) { + location = { labwareId: lw.slot } + } else if (lw.slot === 'offDeck') { + location = 'offDeck' + } else if ( + Object.values(additionalEquipmentOnDeck).find( + ae => ae.location === lw.slot + ) + ) { + const inWasteChute = Object.values(additionalEquipmentOnDeck).find( + ae => ae.location === lw.slot && ae.name === 'wasteChute' + ) + location = { + addressableAreaName: inWasteChute + ? 'gripperWasteChute' + : (lw.slot as AddressableAreaName), + } + } + + return { + id: lw.id, + loadName: lw.def.parameters.loadName, + definitionUri: lw.labwareDefURI, + location, + displayName: labwareNickNames[lw.id], + } + }) + + const liquids: Liquid[] = Object.entries(ingredients).map( + ([liquidId, liquidData]) => ({ + id: liquidId, + displayName: liquidData.name ?? 'undefined liquid name', + description: liquidData.description ?? '', + displayColor: liquidData.displayColor, + }) + ) + + const analysis: CompletedProtocolAnalysis = { + id: uuid(), + result: 'ok', + pipettes: loadPipettes, + labware: loadLabware, + modules: loadModules, + liquids, + commands: runTimeCommands, + errors: [], + robotType, + } + + return +} diff --git a/protocol-designer/src/pages/ProtocolOverview/index.tsx b/protocol-designer/src/pages/ProtocolOverview/index.tsx index e51b47ce799..48b302be234 100644 --- a/protocol-designer/src/pages/ProtocolOverview/index.tsx +++ b/protocol-designer/src/pages/ProtocolOverview/index.tsx @@ -28,6 +28,7 @@ import { import { selectors as fileSelectors } from '../../file-data' import { selectors as stepFormSelectors } from '../../step-forms' import { actions as loadFileActions } from '../../load-file' +import { getEnableTimelineScrubber } from '../../feature-flags/selectors' import { selectors as labwareIngredSelectors } from '../../labware-ingred/selectors' import { MaterialsListModal } from '../../organisms/MaterialsListModal' import { LINE_CLAMP_TEXT_STYLE, COLUMN_STYLE } from '../../atoms' @@ -47,7 +48,7 @@ import { getUnusedStagingAreas, getUnusedTrash, } from './utils' - +import { ScrubberContainer } from './ScrubberContainer' import type { CreateCommand } from '@opentrons/shared-data' import type { ThunkDispatch } from '../../types' @@ -80,6 +81,7 @@ export function ProtocolOverview(): JSX.Element { showEditInstrumentsModal, setShowEditInstrumentsModal, ] = useState(false) + const enableTimelineScrubber = useSelector(getEnableTimelineScrubber) const [showEditMetadataModal, setShowEditMetadataModal] = useState( false ) @@ -322,6 +324,7 @@ export function ProtocolOverview(): JSX.Element { css={COLUMN_STYLE} gridGap={SPACING.spacing12} > + {enableTimelineScrubber ? : null} ( (acc, command) => { if (command.commandType === 'loadPipette' && command.result != null) { @@ -84,6 +83,7 @@ export function getResultingTimelineFrameFromRunCommands( }, {} ) + const initialRobotState = makeInitialRobotState({ invariantContext, labwareLocations, diff --git a/step-generation/src/utils/index.ts b/step-generation/src/utils/index.ts index 88c2ffcc603..a4cee60e039 100644 --- a/step-generation/src/utils/index.ts +++ b/step-generation/src/utils/index.ts @@ -25,4 +25,6 @@ export * from './misc' export * from './movableTrashCommandsUtil' export * from './safePipetteMovements' export * from './wasteChuteCommandsUtil' +export * from './createTimelineFromRunCommands' +export * from './constructInvariantContextFromRunCommands' export const uuid: () => string = uuidv4 From 5303a3b6b3187565e5a437990dd063405cbf9689 Mon Sep 17 00:00:00 2001 From: Seth Foster Date: Wed, 29 Jan 2025 13:11:45 -0500 Subject: [PATCH 17/22] refactor(api): Express labware offset locations as sequences (#17363) This is a pattern that we're going to adopt for symbolic geometry locations in HTTP API contexts - expressing them as a sequence of heterogenous unions that represent kinds of places things can be. We'll do this for locations of labware instances in a followup, but for now we're doing it for offset locations. Offset locations were previously objects that had a slot name; an optional module model, for a location on a module; and an optional labware URI, for a location on a labware (possibly an adapter, possibly on a model). This can't represent labware stacks, and it's locked to slot names. These are more or less fine for now still, but it would be nice to support stacks in the general case, and it will be awkward for clients to use the object-with-optional-attributes model alongside the sequence-of-locations instance model. Plus, while this won't need a database schema change for the offsets stored in runs, it _will_ for the offsets api - so let's make this change now while that schema and API haven't yet shipped. ## Testing - [x] do the offsets still apply, on - [x] a slot - [x] a module - [x] an adapter on a model Since the HTTP API still is the same and everything is tested internally, it is sufficient to do normal LPC testing - everything should still work. ## Reviews - [ ] look appropriate? Missing anything? --- api-client/src/maintenance_runs/types.ts | 4 +- api-client/src/runs/createLabwareOffset.ts | 6 +- api-client/src/runs/createRun.ts | 4 +- api-client/src/runs/types.ts | 30 +- .../protocol_api/core/engine/labware.py | 2 +- .../core/legacy/labware_offset_provider.py | 10 +- api/src/opentrons/protocol_engine/__init__.py | 6 +- .../protocol_engine/actions/actions.py | 4 +- .../protocol_engine/errors/__init__.py | 2 + .../protocol_engine/errors/exceptions.py | 13 + .../protocol_engine/execution/equipment.py | 73 +- .../labware_offset_standardization.py | 172 +++++ .../protocol_engine/protocol_engine.py | 18 +- .../resources/deck_configuration_provider.py | 96 ++- .../protocol_engine/slot_standardization.py | 19 - .../state/addressable_areas.py | 59 +- .../protocol_engine/state/geometry.py | 120 ++- .../protocol_engine/state/labware.py | 34 +- .../protocol_engine/state/modules.py | 7 +- .../protocol_engine/types/__init__.py | 18 +- .../protocol_engine/types/labware.py | 42 +- .../types/labware_offset_location.py | 49 +- .../protocol_engine/types/location.py | 43 +- .../protocol_runner/run_orchestrator.py | 5 +- .../core/engine/test_labware_core.py | 11 +- .../legacy/test_labware_offset_provider.py | 22 +- .../execution/test_equipment_handler.py | 326 +++++++- .../test_labware_movement_handler.py | 4 +- .../test_deck_configuration_provider.py | 14 +- .../state/test_addressable_area_view_old.py | 1 - .../state/test_geometry_view.py | 45 +- .../state/test_labware_store_old.py | 46 +- .../state/test_labware_view_old.py | 78 +- .../test_labware_offset_standardization.py | 725 ++++++++++++++++++ .../protocol_engine/test_protocol_engine.py | 132 +++- .../test_slot_standardization.py | 38 - .../PythonLabwareOffsetSnippet/index.tsx | 4 +- .../useCreateRunFromProtocol.ts | 4 +- .../hooks/useLPCCommands/commands/modules.ts | 4 +- .../useLPCCommands/useApplyLPCOffsets.ts | 6 +- .../useLPCCommands/useBuildOffsetsToApply.ts | 4 +- .../steps/ResultsSummary/OffsetTable.tsx | 4 +- .../steps/ResultsSummary/TableComponent.tsx | 4 +- .../LabwarePositionCheck/types/steps.ts | 4 +- .../hooks/getLabwareLocationCombos.ts | 12 +- .../LabwarePositionCheckComponent.tsx | 6 +- .../ResultsSummary.tsx | 8 +- .../LegacyLabwarePositionCheck/types.ts | 21 +- .../utils/getDisplayLocation.ts | 4 +- .../ProtocolSetupParameters.tsx | 7 +- app/src/organisms/TerseOffsetTable/index.tsx | 4 +- .../protocol-runs/selectors/lpc/labware.ts | 7 +- app/src/redux/protocol-runs/types/lpc.ts | 6 +- .../analysis/getLabwareOffsetLocation.ts | 4 +- .../useCreateLabwareOffsetsMutation.test.tsx | 7 +- .../runs/useCreateLabwareOffsetMutation.ts | 4 +- .../robot_server/labware_offsets/router.py | 9 +- .../robot_server/labware_offsets/store.py | 4 +- .../maintenance_run_data_manager.py | 6 +- .../maintenance_run_models.py | 4 +- .../maintenance_run_orchestrator_store.py | 10 +- .../maintenance_runs/router/labware_router.py | 9 +- .../runs/router/labware_router.py | 8 +- .../robot_server/runs/run_data_manager.py | 5 +- robot-server/robot_server/runs/run_models.py | 4 +- .../runs/run_orchestrator_store.py | 9 +- .../runs/test_protocol_run.tavern.yaml | 6 + .../tests/labware_offsets/test_store.py | 10 +- .../router/test_base_router.py | 9 +- .../router/test_labware_router.py | 7 +- .../maintenance_runs/test_engine_store.py | 12 +- .../maintenance_runs/test_run_data_manager.py | 4 +- .../tests/runs/router/test_base_router.py | 9 +- .../tests/runs/router/test_labware_router.py | 10 +- .../tests/runs/test_run_orchestrator_store.py | 12 +- .../opentrons_shared_data/deck/__init__.py | 5 + 76 files changed, 2080 insertions(+), 474 deletions(-) create mode 100644 api/src/opentrons/protocol_engine/labware_offset_standardization.py create mode 100644 api/tests/opentrons/protocol_engine/test_labware_offset_standardization.py diff --git a/api-client/src/maintenance_runs/types.ts b/api-client/src/maintenance_runs/types.ts index 6696e3ba072..e17c834cd16 100644 --- a/api-client/src/maintenance_runs/types.ts +++ b/api-client/src/maintenance_runs/types.ts @@ -6,7 +6,7 @@ import type { } from '@opentrons/shared-data' import type { RunCommandSummary, - LabwareOffsetCreateData, + LegacyLabwareOffsetCreateData, RunStatus, RunAction, } from '../runs' @@ -42,7 +42,7 @@ export interface MaintenanceRunError { } export interface CreateMaintenanceRunData { - labwareOffsets?: LabwareOffsetCreateData[] + labwareOffsets?: LegacyLabwareOffsetCreateData[] } export interface LabwareDefinitionSummary { diff --git a/api-client/src/runs/createLabwareOffset.ts b/api-client/src/runs/createLabwareOffset.ts index 29da8b61922..0b91566cf46 100644 --- a/api-client/src/runs/createLabwareOffset.ts +++ b/api-client/src/runs/createLabwareOffset.ts @@ -2,14 +2,14 @@ import { POST, request } from '../request' import type { ResponsePromise } from '../request' import type { HostConfig } from '../types' -import type { LabwareOffsetCreateData, Run } from './types' +import type { LegacyLabwareOffsetCreateData, Run } from './types' export function createLabwareOffset( config: HostConfig, runId: string, - data: LabwareOffsetCreateData + data: LegacyLabwareOffsetCreateData ): ResponsePromise { - return request( + return request( POST, `/runs/${runId}/labware_offsets`, { data }, diff --git a/api-client/src/runs/createRun.ts b/api-client/src/runs/createRun.ts index 6e8cd4b7525..e825e55e665 100644 --- a/api-client/src/runs/createRun.ts +++ b/api-client/src/runs/createRun.ts @@ -4,14 +4,14 @@ import type { ResponsePromise } from '../request' import type { HostConfig } from '../types' import type { Run, - LabwareOffsetCreateData, + LegacyLabwareOffsetCreateData, RunTimeParameterValuesCreateData, RunTimeParameterFilesCreateData, } from './types' export interface CreateRunData { protocolId?: string - labwareOffsets?: LabwareOffsetCreateData[] + labwareOffsets?: LegacyLabwareOffsetCreateData[] runTimeParameterValues?: RunTimeParameterValuesCreateData runTimeParameterFiles?: RunTimeParameterFilesCreateData } diff --git a/api-client/src/runs/types.ts b/api-client/src/runs/types.ts index ea24c040ebc..1de9b97717f 100644 --- a/api-client/src/runs/types.ts +++ b/api-client/src/runs/types.ts @@ -85,7 +85,8 @@ export interface LabwareOffset { id: string createdAt: string definitionUri: string - location: LabwareOffsetLocation + location: LegacyLabwareOffsetLocation + locationSequence?: LabwareOffsetLocationSequence vector: VectorOffset } @@ -156,14 +157,35 @@ export interface CreateRunActionData { actionType: RunActionType } -export interface LabwareOffsetLocation { +export interface OnAddressableAreaLabwareOffsetLocationSequenceComponent { + kind: 'onAddressableArea' + labware: string +} + +export interface OnModuleOffsetLocationSequenceComponent { + kind: 'onModule' + moduleModel: ModuleModel +} + +export interface OnLabwareOffsetLocationSequenceComponent { + kind: 'onLabware' + labwareUri: string +} + +export type LabwareOffsetLocationSequenceComponent = + | OnAddressableAreaLabwareOffsetLocationSequenceComponent + | OnModuleOffsetLocationSequenceComponent + | OnLabwareOffsetLocationSequenceComponent +export type LabwareOffsetLocationSequence = LabwareOffsetLocationSequenceComponent[] + +export interface LegacyLabwareOffsetLocation { slotName: string moduleModel?: ModuleModel definitionUri?: string } -export interface LabwareOffsetCreateData { +export interface LegacyLabwareOffsetCreateData { definitionUri: string - location: LabwareOffsetLocation + location: LegacyLabwareOffsetLocation vector: VectorOffset } diff --git a/api/src/opentrons/protocol_api/core/engine/labware.py b/api/src/opentrons/protocol_api/core/engine/labware.py index d462401927f..6a9ea743355 100644 --- a/api/src/opentrons/protocol_api/core/engine/labware.py +++ b/api/src/opentrons/protocol_api/core/engine/labware.py @@ -122,7 +122,7 @@ def set_calibration(self, delta: Point) -> None: request = LabwareOffsetCreate.model_construct( definitionUri=self.get_uri(), - location=offset_location, + locationSequence=offset_location, vector=LabwareOffsetVector(x=delta.x, y=delta.y, z=delta.z), ) self._engine_client.add_labware_offset(request) diff --git a/api/src/opentrons/protocol_api/core/legacy/labware_offset_provider.py b/api/src/opentrons/protocol_api/core/legacy/labware_offset_provider.py index b808cc95add..e0a4b4f6bd2 100644 --- a/api/src/opentrons/protocol_api/core/legacy/labware_offset_provider.py +++ b/api/src/opentrons/protocol_api/core/legacy/labware_offset_provider.py @@ -3,7 +3,11 @@ from typing import Optional from opentrons.hardware_control.modules import ModuleModel as HardwareModuleModel -from opentrons.protocol_engine import ProtocolEngine, LabwareOffsetLocation, ModuleModel +from opentrons.protocol_engine import ( + ProtocolEngine, + LegacyLabwareOffsetLocation, + ModuleModel, +) from opentrons.types import DeckSlotName, Point from ..labware import LabwareLoadParams @@ -81,9 +85,9 @@ def find( See the parent class for param details. """ - offset = self._labware_view.find_applicable_labware_offset( + offset = self._labware_view.find_applicable_labware_offset_by_legacy_location( definition_uri=load_params.as_uri(), - location=LabwareOffsetLocation( + location=LegacyLabwareOffsetLocation( slotName=deck_slot, moduleModel=( None diff --git a/api/src/opentrons/protocol_engine/__init__.py b/api/src/opentrons/protocol_engine/__init__.py index 4b5b2a1f3c3..5e90c7235bf 100644 --- a/api/src/opentrons/protocol_engine/__init__.py +++ b/api/src/opentrons/protocol_engine/__init__.py @@ -26,9 +26,10 @@ from .types import ( LabwareOffset, + LegacyLabwareOffsetCreate, LabwareOffsetCreate, LabwareOffsetVector, - LabwareOffsetLocation, + LegacyLabwareOffsetLocation, LabwareMovementStrategy, AddressableOffsetVector, DeckPoint, @@ -96,7 +97,8 @@ "LabwareOffset", "LabwareOffsetCreate", "LabwareOffsetVector", - "LabwareOffsetLocation", + "LegacyLabwareOffsetCreate", + "LegacyLabwareOffsetLocation", "LabwareMovementStrategy", "AddressableOffsetVector", "DeckSlotLocation", diff --git a/api/src/opentrons/protocol_engine/actions/actions.py b/api/src/opentrons/protocol_engine/actions/actions.py index 0ec505d68e6..680994ce70c 100644 --- a/api/src/opentrons/protocol_engine/actions/actions.py +++ b/api/src/opentrons/protocol_engine/actions/actions.py @@ -23,7 +23,7 @@ from ..notes.notes import CommandNote from ..state.update_types import StateUpdate from ..types import ( - LabwareOffsetCreate, + LabwareOffsetCreateInternal, ModuleDefinition, Liquid, DeckConfigurationType, @@ -206,7 +206,7 @@ class AddLabwareOffsetAction: labware_offset_id: str created_at: datetime - request: LabwareOffsetCreate + request: LabwareOffsetCreateInternal @dataclasses.dataclass(frozen=True) diff --git a/api/src/opentrons/protocol_engine/errors/__init__.py b/api/src/opentrons/protocol_engine/errors/__init__.py index 2b0fb6a6060..85d89e8e2fb 100644 --- a/api/src/opentrons/protocol_engine/errors/__init__.py +++ b/api/src/opentrons/protocol_engine/errors/__init__.py @@ -82,6 +82,7 @@ InvalidLiquidError, LiquidClassDoesNotExistError, LiquidClassRedefinitionError, + OffsetLocationInvalidError, ) from .error_occurrence import ErrorOccurrence, ProtocolCommandFailedError @@ -160,6 +161,7 @@ "LocationIsLidDockSlotError", "InvalidAxisForRobotType", "NotSupportedOnRobotType", + "OffsetLocationInvalidError", # error occurrence models "ErrorOccurrence", "CommandNotAllowedError", diff --git a/api/src/opentrons/protocol_engine/errors/exceptions.py b/api/src/opentrons/protocol_engine/errors/exceptions.py index c3fddf99a61..3aa7c0562ab 100644 --- a/api/src/opentrons/protocol_engine/errors/exceptions.py +++ b/api/src/opentrons/protocol_engine/errors/exceptions.py @@ -433,6 +433,19 @@ def __init__( super().__init__(ErrorCodes.GENERAL_ERROR, message, details, wrapping) +class OffsetLocationInvalidError(ProtocolEngineError): + """Raised when encountering an invalid labware offset location sequence.""" + + def __init__( + self, + message: Optional[str] = None, + details: Optional[Dict[str, Any]] = None, + wrapping: Optional[Sequence[EnumeratedError]] = None, + ) -> None: + """Build an OffsetLocationSequenceDoesNotTerminateAtAnAddressableAreaError.""" + super().__init__(ErrorCodes.GENERAL_ERROR, message, details, wrapping) + + class SlotDoesNotExistError(ProtocolEngineError): """Raised when referencing a deck slot that does not exist.""" diff --git a/api/src/opentrons/protocol_engine/execution/equipment.py b/api/src/opentrons/protocol_engine/execution/equipment.py index b16e26cd6ae..4a487247e08 100644 --- a/api/src/opentrons/protocol_engine/execution/equipment.py +++ b/api/src/opentrons/protocol_engine/execution/equipment.py @@ -1,4 +1,5 @@ """Equipment command side-effect logic.""" + from dataclasses import dataclass from typing import Optional, overload, Union, List @@ -42,10 +43,7 @@ from ..types import ( LabwareLocation, DeckSlotLocation, - ModuleLocation, - OnLabwareLocation, LabwareOffset, - LabwareOffsetLocation, ModuleModel, ModuleDefinition, AddressableAreaLocation, @@ -633,8 +631,9 @@ def find_applicable_labware_offset_id( or None if no labware offset will apply. """ labware_offset_location = ( - self._get_labware_offset_location_from_labware_location(labware_location) + self._state_store.geometry.get_projected_offset_location(labware_location) ) + if labware_offset_location is None: # No offset for off-deck location. # Returning None instead of raising an exception allows loading a labware @@ -647,72 +646,6 @@ def find_applicable_labware_offset_id( ) return self._get_id_from_offset(offset) - def _get_labware_offset_location_from_labware_location( - self, labware_location: LabwareLocation - ) -> Optional[LabwareOffsetLocation]: - if isinstance(labware_location, DeckSlotLocation): - return LabwareOffsetLocation(slotName=labware_location.slotName) - elif isinstance(labware_location, ModuleLocation): - module_id = labware_location.moduleId - # Allow ModuleNotLoadedError to propagate. - # Note also that we match based on the module's requested model, not its - # actual model, to implement robot-server's documented HTTP API semantics. - module_model = self._state_store.modules.get_requested_model( - module_id=module_id - ) - - # If `module_model is None`, it probably means that this module was added by - # `ProtocolEngine.use_attached_modules()`, instead of an explicit - # `loadModule` command. - # - # This assert should never raise in practice because: - # 1. `ProtocolEngine.use_attached_modules()` is only used by - # robot-server's "stateless command" endpoints, under `/commands`. - # 2. Those endpoints don't support loading labware, so this code will - # never run. - # - # Nevertheless, if it does happen somehow, we do NOT want to pass the - # `None` value along to `LabwareView.find_applicable_labware_offset()`. - # `None` means something different there, which will cause us to return - # wrong results. - assert module_model is not None, ( - "Can't find offsets for labware" - " that are loaded on modules" - " that were loaded with ProtocolEngine.use_attached_modules()." - ) - - module_location = self._state_store.modules.get_location( - module_id=module_id - ) - slot_name = module_location.slotName - return LabwareOffsetLocation(slotName=slot_name, moduleModel=module_model) - elif isinstance(labware_location, OnLabwareLocation): - parent_labware_id = labware_location.labwareId - parent_labware_uri = self._state_store.labware.get_definition_uri( - parent_labware_id - ) - - base_location = self._state_store.labware.get_parent_location( - parent_labware_id - ) - base_labware_offset_location = ( - self._get_labware_offset_location_from_labware_location(base_location) - ) - if base_labware_offset_location is None: - # No offset for labware sitting on labware off-deck - return None - - # If labware is being stacked on itself, all labware in the stack will share a labware offset due to - # them sharing the same definitionUri in `LabwareOffsetLocation`. This will not be true for the - # bottom-most labware, which will have a `DeckSlotLocation` and have its definitionUri field empty. - return LabwareOffsetLocation( - slotName=base_labware_offset_location.slotName, - moduleModel=base_labware_offset_location.moduleModel, - definitionUri=parent_labware_uri, - ) - else: # Off deck - return None - @staticmethod def _get_id_from_offset(labware_offset: Optional[LabwareOffset]) -> Optional[str]: return None if labware_offset is None else labware_offset.id diff --git a/api/src/opentrons/protocol_engine/labware_offset_standardization.py b/api/src/opentrons/protocol_engine/labware_offset_standardization.py new file mode 100644 index 00000000000..836d40cb700 --- /dev/null +++ b/api/src/opentrons/protocol_engine/labware_offset_standardization.py @@ -0,0 +1,172 @@ +"""Convert labware offset creation requests and stored elements between legacy and new.""" + +from opentrons_shared_data.robot.types import RobotType +from opentrons_shared_data.deck.types import DeckDefinitionV5 +from .errors import ( + OffsetLocationInvalidError, + FixtureDoesNotExistError, +) +from .types import ( + LabwareOffsetCreate, + LegacyLabwareOffsetCreate, + LabwareOffsetCreateInternal, + LegacyLabwareOffsetLocation, + LabwareOffsetLocationSequence, + OnLabwareOffsetLocationSequenceComponent, + OnAddressableAreaOffsetLocationSequenceComponent, + OnModuleOffsetLocationSequenceComponent, + ModuleModel, +) +from .resources import deck_configuration_provider + + +def standardize_labware_offset_create( + request: LabwareOffsetCreate | LegacyLabwareOffsetCreate, + robot_type: RobotType, + deck_definition: DeckDefinitionV5, +) -> LabwareOffsetCreateInternal: + """Turn a union of old and new labware offset create requests into a new one.""" + location_sequence, legacy_location = _locations_for_create( + request, robot_type, deck_definition + ) + return LabwareOffsetCreateInternal( + definitionUri=request.definitionUri, + locationSequence=location_sequence, + legacyLocation=legacy_location, + vector=request.vector, + ) + + +def _legacy_offset_location_to_offset_location_sequence( + location: LegacyLabwareOffsetLocation, deck_definition: DeckDefinitionV5 +) -> LabwareOffsetLocationSequence: + sequence: LabwareOffsetLocationSequence = [] + if location.definitionUri: + sequence.append( + OnLabwareOffsetLocationSequenceComponent(labwareUri=location.definitionUri) + ) + if location.moduleModel: + sequence.append( + OnModuleOffsetLocationSequenceComponent(moduleModel=location.moduleModel) + ) + cutout_id = deck_configuration_provider.get_cutout_id_by_deck_slot_name( + location.slotName + ) + possible_cutout_fixture_id = location.moduleModel.value + try: + addressable_area = deck_configuration_provider.get_labware_hosting_addressable_area_name_for_cutout_and_cutout_fixture( + cutout_id, possible_cutout_fixture_id, deck_definition + ) + sequence.append( + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName=addressable_area + ) + ) + except FixtureDoesNotExistError: + # this is an OT-2 (or this module isn't supported in the deck definition) and we should use a + # slot addressable area name + sequence.append( + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName=location.slotName.value + ) + ) + + else: + # Slight hack: we should have a more formal association here. However, since the slot + # name is already standardized, and since the addressable areas for slots are just the + # name of the slots, we can rely on this. + sequence.append( + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName=location.slotName.value + ) + ) + return sequence + + +def _offset_location_sequence_head_to_labware_and_module( + location_sequence: LabwareOffsetLocationSequence, +) -> tuple[ModuleModel | None, str | None]: + labware_uri: str | None = None + module_model: ModuleModel | None = None + for location in location_sequence: + if isinstance(location, OnAddressableAreaOffsetLocationSequenceComponent): + raise OffsetLocationInvalidError( + "Addressable areas may only be the final element of an offset location." + ) + elif isinstance(location, OnLabwareOffsetLocationSequenceComponent): + if labware_uri is not None: + # We only take the first location + continue + if module_model is not None: + # Labware can't be underneath modules + raise OffsetLocationInvalidError( + "Labware must not be underneath a module." + ) + labware_uri = location.labwareUri + elif isinstance(location, OnModuleOffsetLocationSequenceComponent): + if module_model is not None: + # Bad, somebody put more than one module in here + raise OffsetLocationInvalidError( + "Only one module location may exist in an offset location." + ) + module_model = location.moduleModel + else: + raise OffsetLocationInvalidError( + f"Invalid location component in offset location: {repr(location)}" + ) + return module_model, labware_uri + + +def _offset_location_sequence_to_legacy_offset_location( + location_sequence: LabwareOffsetLocationSequence, deck_definition: DeckDefinitionV5 +) -> LegacyLabwareOffsetLocation: + if len(location_sequence) == 0: + raise OffsetLocationInvalidError( + "Offset locations must contain at least one component." + ) + last_element = location_sequence[-1] + if not isinstance(last_element, OnAddressableAreaOffsetLocationSequenceComponent): + raise OffsetLocationInvalidError( + "Offset locations must end with an addressable area." + ) + module_model, labware_uri = _offset_location_sequence_head_to_labware_and_module( + location_sequence[:-1] + ) + ( + cutout_id, + cutout_fixtures, + ) = deck_configuration_provider.get_potential_cutout_fixtures( + last_element.addressableAreaName, deck_definition + ) + slot_name = deck_configuration_provider.get_deck_slot_for_cutout_id(cutout_id) + return LegacyLabwareOffsetLocation( + slotName=slot_name, moduleModel=module_model, definitionUri=labware_uri + ) + + +def _locations_for_create( + request: LabwareOffsetCreate | LegacyLabwareOffsetCreate, + robot_type: RobotType, + deck_definition: DeckDefinitionV5, +) -> tuple[LabwareOffsetLocationSequence, LegacyLabwareOffsetLocation]: + if isinstance(request, LabwareOffsetCreate): + return ( + request.locationSequence, + _offset_location_sequence_to_legacy_offset_location( + request.locationSequence, deck_definition + ), + ) + else: + normalized = request.location.model_copy( + update={ + "slotName": request.location.slotName.to_equivalent_for_robot_type( + robot_type + ) + } + ) + return ( + _legacy_offset_location_to_offset_location_sequence( + normalized, deck_definition + ), + normalized, + ) diff --git a/api/src/opentrons/protocol_engine/protocol_engine.py b/api/src/opentrons/protocol_engine/protocol_engine.py index d1636d18001..04579efc590 100644 --- a/api/src/opentrons/protocol_engine/protocol_engine.py +++ b/api/src/opentrons/protocol_engine/protocol_engine.py @@ -1,4 +1,5 @@ """ProtocolEngine class definition.""" + from contextlib import AsyncExitStack from logging import getLogger from typing import Dict, Optional, Union, AsyncGenerator, Callable @@ -20,11 +21,12 @@ from .errors import ProtocolCommandFailedError, ErrorOccurrence, CommandNotAllowedError from .errors.exceptions import EStopActivatedError from .error_recovery_policy import ErrorRecoveryPolicy -from . import commands, slot_standardization +from . import commands, slot_standardization, labware_offset_standardization from .resources import ModelUtils, ModuleDataProvider, FileProvider from .types import ( LabwareOffset, LabwareOffsetCreate, + LegacyLabwareOffsetCreate, LabwareUri, ModuleModel, Liquid, @@ -517,15 +519,21 @@ async def finish( ) ) - def add_labware_offset(self, request: LabwareOffsetCreate) -> LabwareOffset: + def add_labware_offset( + self, request: LabwareOffsetCreate | LegacyLabwareOffsetCreate + ) -> LabwareOffset: """Add a new labware offset and return it. The added offset will apply to subsequent `LoadLabwareCommand`s. To retrieve offsets later, see `.state_view.labware`. """ - request = slot_standardization.standardize_labware_offset( - request, self.state_view.config.robot_type + internal_request = ( + labware_offset_standardization.standardize_labware_offset_create( + request, + self.state_view.config.robot_type, + self.state_view.addressable_areas.deck_definition, + ) ) labware_offset_id = self._model_utils.generate_id() @@ -534,7 +542,7 @@ def add_labware_offset(self, request: LabwareOffsetCreate) -> LabwareOffset: AddLabwareOffsetAction( labware_offset_id=labware_offset_id, created_at=created_at, - request=request, + request=internal_request, ) ) return self.state_view.labware.get_labware_offset( diff --git a/api/src/opentrons/protocol_engine/resources/deck_configuration_provider.py b/api/src/opentrons/protocol_engine/resources/deck_configuration_provider.py index 739d56ded00..6ec09136387 100644 --- a/api/src/opentrons/protocol_engine/resources/deck_configuration_provider.py +++ b/api/src/opentrons/protocol_engine/resources/deck_configuration_provider.py @@ -1,7 +1,11 @@ """Deck configuration resource provider.""" + from typing import List, Set, Tuple -from opentrons_shared_data.deck.types import DeckDefinitionV5, CutoutFixture +from opentrons_shared_data.deck.types import ( + DeckDefinitionV5, + CutoutFixture, +) from opentrons.types import DeckSlotName @@ -17,6 +21,7 @@ CutoutDoesNotExistError, FixtureDoesNotExistError, AddressableAreaDoesNotExistError, + SlotDoesNotExistError, ) @@ -98,12 +103,15 @@ def get_potential_cutout_fixtures( def get_addressable_area_from_name( addressable_area_name: str, cutout_position: DeckPoint, - base_slot: DeckSlotName, deck_definition: DeckDefinitionV5, ) -> AddressableArea: """Given a name and a cutout position, get an addressable area on the deck.""" for addressable_area in deck_definition["locations"]["addressableAreas"]: if addressable_area["id"] == addressable_area_name: + cutout_id, _ = get_potential_cutout_fixtures( + addressable_area_name, deck_definition + ) + base_slot = get_deck_slot_for_cutout_id(cutout_id) area_offset = addressable_area["offsetFromCutoutFixture"] position = AddressableOffsetVector( x=area_offset[0] + cutout_position.x, @@ -130,3 +138,87 @@ def get_addressable_area_from_name( raise AddressableAreaDoesNotExistError( f"Could not find addressable area with name {addressable_area_name}" ) + + +def get_deck_slot_for_cutout_id(cutout_id: str) -> DeckSlotName: + """Get the corresponding deck slot for an addressable area.""" + try: + return CUTOUT_TO_DECK_SLOT_MAP[cutout_id] + except KeyError: + raise CutoutDoesNotExistError(f"Could not find data for cutout {cutout_id}") + + +def get_cutout_id_by_deck_slot_name(slot_name: DeckSlotName) -> str: + """Get the Cutout ID of a given Deck Slot by Deck Slot Name.""" + try: + return DECK_SLOT_TO_CUTOUT_MAP[slot_name] + except KeyError: + raise SlotDoesNotExistError(f"Could not find data for slot {slot_name.value}") + + +def get_labware_hosting_addressable_area_name_for_cutout_and_cutout_fixture( + cutout_id: str, cutout_fixture_id: str, deck_definition: DeckDefinitionV5 +) -> str: + """Get the first addressable area that can contain labware for a cutout and fixture. + + This probably isn't relevant outside of labware offset locations, where (for now) nothing + provides more than one labware-containing addressable area. + """ + for cutoutFixture in deck_definition["cutoutFixtures"]: + if cutoutFixture["id"] != cutout_fixture_id: + continue + provided_aas = cutoutFixture["providesAddressableAreas"].get(cutout_id, None) + if provided_aas is None: + raise CutoutDoesNotExistError( + f"{cutout_fixture_id} does not go in {cutout_id}" + ) + for aa_id in provided_aas: + for addressable_area in deck_definition["locations"]["addressableAreas"]: + if addressable_area["id"] != aa_id: + continue + # TODO: In deck def v6 this will be easier, but as of right now there isn't really + # a way to tell from an addressable area whether it takes labware so let's take the + # first one + return aa_id + raise AddressableAreaDoesNotExistError( + f"Could not find an addressable area that allows labware from cutout fixture {cutout_fixture_id} in cutout {cutout_id}" + ) + + raise FixtureDoesNotExistError(f"Could not find entry for {cutout_fixture_id}") + + +# This is a temporary shim while Protocol Engine's conflict-checking code +# can only take deck slots as input. +# Long-term solution: Check for conflicts based on bounding boxes, not slot adjacencies. +# Shorter-term: Change the conflict-checking code to take cutouts instead of deck slots. +CUTOUT_TO_DECK_SLOT_MAP: dict[str, DeckSlotName] = { + # OT-2 + "cutout1": DeckSlotName.SLOT_1, + "cutout2": DeckSlotName.SLOT_2, + "cutout3": DeckSlotName.SLOT_3, + "cutout4": DeckSlotName.SLOT_4, + "cutout5": DeckSlotName.SLOT_5, + "cutout6": DeckSlotName.SLOT_6, + "cutout7": DeckSlotName.SLOT_7, + "cutout8": DeckSlotName.SLOT_8, + "cutout9": DeckSlotName.SLOT_9, + "cutout10": DeckSlotName.SLOT_10, + "cutout11": DeckSlotName.SLOT_11, + "cutout12": DeckSlotName.FIXED_TRASH, + # Flex + "cutoutA1": DeckSlotName.SLOT_A1, + "cutoutA2": DeckSlotName.SLOT_A2, + "cutoutA3": DeckSlotName.SLOT_A3, + "cutoutB1": DeckSlotName.SLOT_B1, + "cutoutB2": DeckSlotName.SLOT_B2, + "cutoutB3": DeckSlotName.SLOT_B3, + "cutoutC1": DeckSlotName.SLOT_C1, + "cutoutC2": DeckSlotName.SLOT_C2, + "cutoutC3": DeckSlotName.SLOT_C3, + "cutoutD1": DeckSlotName.SLOT_D1, + "cutoutD2": DeckSlotName.SLOT_D2, + "cutoutD3": DeckSlotName.SLOT_D3, +} +DECK_SLOT_TO_CUTOUT_MAP = { + deck_slot: cutout for cutout, deck_slot in CUTOUT_TO_DECK_SLOT_MAP.items() +} diff --git a/api/src/opentrons/protocol_engine/slot_standardization.py b/api/src/opentrons/protocol_engine/slot_standardization.py index 5943febc820..935bb54da3f 100644 --- a/api/src/opentrons/protocol_engine/slot_standardization.py +++ b/api/src/opentrons/protocol_engine/slot_standardization.py @@ -14,7 +14,6 @@ deck slot. """ - from typing import Any, Callable, Dict, Type from opentrons_shared_data.robot.types import RobotType @@ -26,29 +25,11 @@ DeckSlotLocation, LabwareLocation, AddressableAreaLocation, - LabwareOffsetCreate, ModuleLocation, OnLabwareLocation, ) -def standardize_labware_offset( - original: LabwareOffsetCreate, robot_type: RobotType -) -> LabwareOffsetCreate: - """Convert the deck slot in the given `LabwareOffsetCreate` to match the given robot type.""" - return original.model_copy( - update={ - "location": original.location.model_copy( - update={ - "slotName": original.location.slotName.to_equivalent_for_robot_type( - robot_type - ) - } - ) - } - ) - - def standardize_command( original: commands.CommandCreate, robot_type: RobotType ) -> commands.CommandCreate: diff --git a/api/src/opentrons/protocol_engine/state/addressable_areas.py b/api/src/opentrons/protocol_engine/state/addressable_areas.py index 16898ccb4ed..c227fa72285 100644 --- a/api/src/opentrons/protocol_engine/state/addressable_areas.py +++ b/api/src/opentrons/protocol_engine/state/addressable_areas.py @@ -1,4 +1,5 @@ """Basic addressable area data state and store.""" + from dataclasses import dataclass from functools import cached_property from typing import Dict, List, Optional, Set @@ -112,43 +113,6 @@ def _get_conflicting_addressable_areas_error_string( return ", ".join(display_names) -# This is a temporary shim while Protocol Engine's conflict-checking code -# can only take deck slots as input. -# Long-term solution: Check for conflicts based on bounding boxes, not slot adjacencies. -# Shorter-term: Change the conflict-checking code to take cutouts instead of deck slots. -CUTOUT_TO_DECK_SLOT_MAP: Dict[str, DeckSlotName] = { - # OT-2 - "cutout1": DeckSlotName.SLOT_1, - "cutout2": DeckSlotName.SLOT_2, - "cutout3": DeckSlotName.SLOT_3, - "cutout4": DeckSlotName.SLOT_4, - "cutout5": DeckSlotName.SLOT_5, - "cutout6": DeckSlotName.SLOT_6, - "cutout7": DeckSlotName.SLOT_7, - "cutout8": DeckSlotName.SLOT_8, - "cutout9": DeckSlotName.SLOT_9, - "cutout10": DeckSlotName.SLOT_10, - "cutout11": DeckSlotName.SLOT_11, - "cutout12": DeckSlotName.FIXED_TRASH, - # Flex - "cutoutA1": DeckSlotName.SLOT_A1, - "cutoutA2": DeckSlotName.SLOT_A2, - "cutoutA3": DeckSlotName.SLOT_A3, - "cutoutB1": DeckSlotName.SLOT_B1, - "cutoutB2": DeckSlotName.SLOT_B2, - "cutoutB3": DeckSlotName.SLOT_B3, - "cutoutC1": DeckSlotName.SLOT_C1, - "cutoutC2": DeckSlotName.SLOT_C2, - "cutoutC3": DeckSlotName.SLOT_C3, - "cutoutD1": DeckSlotName.SLOT_D1, - "cutoutD2": DeckSlotName.SLOT_D2, - "cutoutD3": DeckSlotName.SLOT_D3, -} -DECK_SLOT_TO_CUTOUT_MAP = { - deck_slot: cutout for cutout, deck_slot in CUTOUT_TO_DECK_SLOT_MAP.items() -} - - class AddressableAreaStore(HasState[AddressableAreaState], HandlesActions): """Addressable area state container.""" @@ -221,13 +185,11 @@ def _get_addressable_areas_from_deck_configuration( cutout_position = deck_configuration_provider.get_cutout_position( cutout_id, deck_definition ) - base_slot = CUTOUT_TO_DECK_SLOT_MAP[cutout_id] for addressable_area_name in provided_addressable_areas: addressable_areas.append( deck_configuration_provider.get_addressable_area_from_name( addressable_area_name=addressable_area_name, cutout_position=cutout_position, - base_slot=base_slot, deck_definition=deck_definition, ) ) @@ -242,12 +204,10 @@ def _add_addressable_area(self, addressable_area_name: str) -> None: cutout_position = deck_configuration_provider.get_cutout_position( cutout_id, self._state.deck_definition ) - base_slot = CUTOUT_TO_DECK_SLOT_MAP[cutout_id] addressable_area = ( deck_configuration_provider.get_addressable_area_from_name( addressable_area_name=addressable_area_name, cutout_position=cutout_position, - base_slot=base_slot, deck_definition=self._state.deck_definition, ) ) @@ -300,6 +260,11 @@ def __init__(self, state: AddressableAreaState) -> None: """ self._state = state + @cached_property + def deck_definition(self) -> DeckDefinitionV5: + """The full deck definition.""" + return self._state.deck_definition + @cached_property def deck_extents(self) -> Point: """The maximum space on the deck.""" @@ -426,11 +391,9 @@ def _get_addressable_area_from_deck_data( cutout_position = deck_configuration_provider.get_cutout_position( cutout_id, self._state.deck_definition ) - base_slot = CUTOUT_TO_DECK_SLOT_MAP[cutout_id] return deck_configuration_provider.get_addressable_area_from_name( addressable_area_name=addressable_area_name, cutout_position=cutout_position, - base_slot=base_slot, deck_definition=self._state.deck_definition, ) @@ -526,7 +489,7 @@ def get_addressable_area_center(self, addressable_area_name: str) -> Point: def get_cutout_id_by_deck_slot_name(self, slot_name: DeckSlotName) -> str: """Get the Cutout ID of a given Deck Slot by Deck Slot Name.""" - return DECK_SLOT_TO_CUTOUT_MAP[slot_name] + return deck_configuration_provider.get_cutout_id_by_deck_slot_name(slot_name) def get_fixture_by_deck_slot_name( self, slot_name: DeckSlotName @@ -534,7 +497,9 @@ def get_fixture_by_deck_slot_name( """Get the Cutout Fixture currently loaded where a specific Deck Slot would be.""" deck_config = self._state.deck_configuration if deck_config: - slot_cutout_id = DECK_SLOT_TO_CUTOUT_MAP[slot_name] + slot_cutout_id = ( + deck_configuration_provider.get_cutout_id_by_deck_slot_name(slot_name) + ) slot_cutout_fixture = None # This will only ever be one under current assumptions for ( @@ -571,7 +536,9 @@ def get_fixture_serial_from_deck_configuration_by_deck_slot( """Get the serial number provided by the deck configuration for a Fixture at a given location.""" deck_config = self._state.deck_configuration if deck_config: - slot_cutout_id = DECK_SLOT_TO_CUTOUT_MAP[slot_name] + slot_cutout_id = ( + deck_configuration_provider.get_cutout_id_by_deck_slot_name(slot_name) + ) # This will only ever be one under current assumptions for ( cutout_id, diff --git a/api/src/opentrons/protocol_engine/state/geometry.py b/api/src/opentrons/protocol_engine/state/geometry.py index 9a817564c67..adebf800082 100644 --- a/api/src/opentrons/protocol_engine/state/geometry.py +++ b/api/src/opentrons/protocol_engine/state/geometry.py @@ -51,7 +51,10 @@ AddressableAreaLocation, AddressableOffsetVector, StagingSlotLocation, - LabwareOffsetLocation, + LabwareOffsetLocationSequence, + OnModuleOffsetLocationSequenceComponent, + OnAddressableAreaOffsetLocationSequenceComponent, + OnLabwareOffsetLocationSequenceComponent, ModuleModel, ) from .config import Config @@ -1361,50 +1364,91 @@ def _labware_gripper_offsets( labware_id=labware_id, slot_name=None ) - def get_offset_location(self, labware_id: str) -> Optional[LabwareOffsetLocation]: - """Provide the LabwareOffsetLocation specifying the current position of the labware. + def get_offset_location( + self, labware_id: str + ) -> Optional[LabwareOffsetLocationSequence]: + """Provide the LegacyLabwareOffsetLocation specifying the current position of the labware. - If the labware is in a location that cannot be specified by a LabwareOffsetLocation + If the labware is in a location that cannot be specified by a LabwareOffsetLocationSequence (for instance, OFF_DECK) then return None. """ parent_location = self._labware.get_location(labware_id) - - if isinstance(parent_location, DeckSlotLocation): - return LabwareOffsetLocation( - slotName=parent_location.slotName, moduleModel=None, definitionUri=None - ) - elif isinstance(parent_location, ModuleLocation): - module_model = self._modules.get_requested_model(parent_location.moduleId) - module_location = self._modules.get_location(parent_location.moduleId) - return LabwareOffsetLocation( - slotName=module_location.slotName, - moduleModel=module_model, - definitionUri=None, - ) - elif isinstance(parent_location, OnLabwareLocation): - non_labware_parent_location = self._labware.get_parent_location(labware_id) - - parent_uri = self._labware.get_definition_uri(parent_location.labwareId) - if isinstance(non_labware_parent_location, DeckSlotLocation): - return LabwareOffsetLocation( - slotName=non_labware_parent_location.slotName, - moduleModel=None, - definitionUri=parent_uri, - ) - elif isinstance(non_labware_parent_location, ModuleLocation): - module_model = self._modules.get_requested_model( - non_labware_parent_location.moduleId + return self.get_projected_offset_location(parent_location) + + def get_projected_offset_location( + self, labware_location: LabwareLocation + ) -> Optional[LabwareOffsetLocationSequence]: + """Get the offset location that a labware loaded into this location would match.""" + return self._recurse_labware_offset_location(labware_location, []) + + def _recurse_labware_offset_location( + self, labware_location: LabwareLocation, building: LabwareOffsetLocationSequence + ) -> LabwareOffsetLocationSequence | None: + if isinstance(labware_location, DeckSlotLocation): + return building + [ + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName=labware_location.slotName.value ) - module_location = self._modules.get_location( - non_labware_parent_location.moduleId - ) - return LabwareOffsetLocation( - slotName=module_location.slotName, - moduleModel=module_model, - definitionUri=parent_uri, + ] + + elif isinstance(labware_location, ModuleLocation): + module_id = labware_location.moduleId + # Allow ModuleNotLoadedError to propagate. + # Note also that we match based on the module's requested model, not its + # actual model, to implement robot-server's documented HTTP API semantics. + module_model = self._modules.get_requested_model(module_id=module_id) + + # If `module_model is None`, it probably means that this module was added by + # `ProtocolEngine.use_attached_modules()`, instead of an explicit + # `loadModule` command. + # + # This assert should never raise in practice because: + # 1. `ProtocolEngine.use_attached_modules()` is only used by + # robot-server's "stateless command" endpoints, under `/commands`. + # 2. Those endpoints don't support loading labware, so this code will + # never run. + # + # Nevertheless, if it does happen somehow, we do NOT want to pass the + # `None` value along to `LabwareView.find_applicable_labware_offset()`. + # `None` means something different there, which will cause us to return + # wrong results. + assert module_model is not None, ( + "Can't find offsets for labware" + " that are loaded on modules" + " that were loaded with ProtocolEngine.use_attached_modules()." + ) + + module_location = self._modules.get_location(module_id=module_id) + if self._modules.get_deck_supports_module_fixtures(): + module_aa = self._modules.ensure_and_convert_module_fixture_location( + module_location.slotName, module_model ) + else: + module_aa = module_location.slotName.value + return building + [ + OnModuleOffsetLocationSequenceComponent(moduleModel=module_model), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName=module_aa + ), + ] + + elif isinstance(labware_location, OnLabwareLocation): + parent_labware_id = labware_location.labwareId + parent_labware_uri = self._labware.get_definition_uri(parent_labware_id) + + base_location = self._labware.get_parent_location(parent_labware_id) + return self._recurse_labware_offset_location( + base_location, + building + + [ + OnLabwareOffsetLocationSequenceComponent( + labwareUri=parent_labware_uri + ) + ], + ) - return None + else: # Off deck + return None def get_well_offset_adjustment( self, diff --git a/api/src/opentrons/protocol_engine/state/labware.py b/api/src/opentrons/protocol_engine/state/labware.py index c4a2afcd62f..6063a46e6b8 100644 --- a/api/src/opentrons/protocol_engine/state/labware.py +++ b/api/src/opentrons/protocol_engine/state/labware.py @@ -1,4 +1,5 @@ """Basic labware data state and store.""" + from __future__ import annotations from dataclasses import dataclass @@ -41,7 +42,8 @@ Dimensions, LabwareOffset, LabwareOffsetVector, - LabwareOffsetLocation, + LabwareOffsetLocationSequence, + LegacyLabwareOffsetLocation, LabwareLocation, LoadedLabware, ModuleLocation, @@ -167,7 +169,8 @@ def handle_action(self, action: Action) -> None: id=action.labware_offset_id, createdAt=action.created_at, definitionUri=action.request.definitionUri, - location=action.request.location, + location=action.request.legacyLocation, + locationSequence=action.request.locationSequence, vector=action.request.vector, ) self._add_labware_offset(labware_offset) @@ -825,15 +828,32 @@ def get_labware_offsets(self) -> List[LabwareOffset]: """Get all labware offsets, in the order they were added.""" return list(self._state.labware_offsets_by_id.values()) - # TODO: Make this slightly more ergonomic for the caller by - # only returning the optional str ID, at the cost of baking redundant lookups - # into the API? def find_applicable_labware_offset( + self, definition_uri: str, location: LabwareOffsetLocationSequence + ) -> Optional[LabwareOffset]: + """Find a labware offset that applies to the given definition and location sequence. + + Returns the *most recently* added matching offset, so later ones can override earlier ones. + Returns ``None`` if no loaded offset matches the location. + + An offset matches a labware instance if the sequence of locations formed by following the + .location elements of the labware instance until you reach an addressable area has the same + definition URIs as the sequence of definition URIs stored by the offset. + """ + for candidate in reversed(list(self._state.labware_offsets_by_id.values())): + if ( + candidate.definitionUri == definition_uri + and candidate.locationSequence == location + ): + return candidate + return None + + def find_applicable_labware_offset_by_legacy_location( self, definition_uri: str, - location: LabwareOffsetLocation, + location: LegacyLabwareOffsetLocation, ) -> Optional[LabwareOffset]: - """Find a labware offset that applies to the given definition and location. + """Find a labware offset that applies to the given definition and legacy location. Returns the *most recently* added matching offset, so later offsets can override earlier ones. diff --git a/api/src/opentrons/protocol_engine/state/modules.py b/api/src/opentrons/protocol_engine/state/modules.py index 2717f2a6984..8fdfd44ee4f 100644 --- a/api/src/opentrons/protocol_engine/state/modules.py +++ b/api/src/opentrons/protocol_engine/state/modules.py @@ -1296,6 +1296,11 @@ def convert_absorbance_reader_data_points( "Only readings of 96 Well labware are supported for conversion to map of values by well." ) + def get_deck_supports_module_fixtures(self) -> bool: + """Check if the loaded deck supports modules as fixtures.""" + deck_type = self._state.deck_type + return deck_type not in [DeckType.OT2_STANDARD, DeckType.OT2_SHORT_TRASH] + def ensure_and_convert_module_fixture_location( self, deck_slot: DeckSlotName, @@ -1307,7 +1312,7 @@ def ensure_and_convert_module_fixture_location( """ deck_type = self._state.deck_type - if deck_type == DeckType.OT2_STANDARD or deck_type == DeckType.OT2_SHORT_TRASH: + if not self.get_deck_supports_module_fixtures(): raise ValueError( f"Invalid Deck Type: {deck_type.name} - Does not support modules as fixtures." ) diff --git a/api/src/opentrons/protocol_engine/types/__init__.py b/api/src/opentrons/protocol_engine/types/__init__.py index 9bf512a7a29..fbaef870f3e 100644 --- a/api/src/opentrons/protocol_engine/types/__init__.py +++ b/api/src/opentrons/protocol_engine/types/__init__.py @@ -83,10 +83,18 @@ OverlapOffset, LabwareOffset, LabwareOffsetCreate, + LegacyLabwareOffsetCreate, + LabwareOffsetCreateInternal, LoadedLabware, ) from .liquid import HexColor, EmptyLiquidId, LiquidId, Liquid, FluidKind, AspiratedFluid -from .labware_offset_location import LabwareOffsetLocation +from .labware_offset_location import ( + LegacyLabwareOffsetLocation, + LabwareOffsetLocationSequence, + OnLabwareOffsetLocationSequenceComponent, + OnModuleOffsetLocationSequenceComponent, + OnAddressableAreaOffsetLocationSequenceComponent, +) from .labware_offset_vector import LabwareOffsetVector from .well_position import ( WellOrigin, @@ -194,13 +202,19 @@ "NonStackedLocation", "DeckPoint", # Labware offset location - "LabwareOffsetLocation", + "LegacyLabwareOffsetLocation", + "LabwareOffsetLocationSequence", + "OnLabwareOffsetLocationSequenceComponent", + "OnModuleOffsetLocationSequenceComponent", + "OnAddressableAreaOffsetLocationSequenceComponent", # Labware offset vector "LabwareOffsetVector", # Labware "OverlapOffset", "LabwareOffset", "LabwareOffsetCreate", + "LegacyLabwareOffsetCreate", + "LabwareOffsetCreateInternal", "LoadedLabware", "LabwareOffsetVector", # Liquids diff --git a/api/src/opentrons/protocol_engine/types/labware.py b/api/src/opentrons/protocol_engine/types/labware.py index b0dd5d52d31..bb8a4656d58 100644 --- a/api/src/opentrons/protocol_engine/types/labware.py +++ b/api/src/opentrons/protocol_engine/types/labware.py @@ -3,12 +3,16 @@ from __future__ import annotations from typing import Optional +from dataclasses import dataclass from datetime import datetime from pydantic import BaseModel, Field from .location import LabwareLocation -from .labware_offset_location import LabwareOffsetLocation +from .labware_offset_location import ( + LegacyLabwareOffsetLocation, + LabwareOffsetLocationSequence, +) from .labware_offset_vector import LabwareOffsetVector from .util import Vec3f @@ -28,9 +32,13 @@ class LabwareOffset(BaseModel): id: str = Field(..., description="Unique labware offset record identifier.") createdAt: datetime = Field(..., description="When this labware offset was added.") definitionUri: str = Field(..., description="The URI for the labware's definition.") - location: LabwareOffsetLocation = Field( + location: LegacyLabwareOffsetLocation = Field( ..., - description="Where the labware is located on the robot.", + description="Where the labware is located on the robot. Deprecated and present only for backwards compatibility; cannot represent certain locations. Use locationSequence instead.", + ) + locationSequence: Optional[LabwareOffsetLocationSequence] = Field( + default=None, + description="Where the labware is located on the robot. Can represent all locations, but may not be present for older runs.", ) vector: LabwareOffsetVector = Field( ..., @@ -38,11 +46,11 @@ class LabwareOffset(BaseModel): ) -class LabwareOffsetCreate(BaseModel): - """Create request data for a labware offset.""" +class LegacyLabwareOffsetCreate(BaseModel): + """Create request data for a labware offset with a legacy location field.""" definitionUri: str = Field(..., description="The URI for the labware's definition.") - location: LabwareOffsetLocation = Field( + location: LegacyLabwareOffsetLocation = Field( ..., description="Where the labware is located on the robot.", ) @@ -52,6 +60,28 @@ class LabwareOffsetCreate(BaseModel): ) +class LabwareOffsetCreate(BaseModel): + """Create request data for a labware offset with a modern location sequence.""" + + definitionUri: str = Field(..., description="The URI for the labware's definition.") + locationSequence: LabwareOffsetLocationSequence = Field( + ..., description="Where the labware is located on the robot." + ) + vector: LabwareOffsetVector = Field( + ..., description="The offset applied to matching labware." + ) + + +@dataclass(frozen=True) +class LabwareOffsetCreateInternal: + """An internal-only labware offset creator that captures both old and new location arguments.""" + + definitionUri: str + locationSequence: LabwareOffsetLocationSequence + legacyLocation: LegacyLabwareOffsetLocation + vector: LabwareOffsetVector + + class LoadedLabware(BaseModel): """A labware that has been loaded.""" diff --git a/api/src/opentrons/protocol_engine/types/labware_offset_location.py b/api/src/opentrons/protocol_engine/types/labware_offset_location.py index cf7496be2e0..2b992a4da01 100644 --- a/api/src/opentrons/protocol_engine/types/labware_offset_location.py +++ b/api/src/opentrons/protocol_engine/types/labware_offset_location.py @@ -3,7 +3,7 @@ This is its own module to fix circular imports. """ -from typing import Optional +from typing import Optional, Literal from pydantic import BaseModel, Field @@ -12,7 +12,52 @@ from .module import ModuleModel -class LabwareOffsetLocation(BaseModel): +class OnLabwareOffsetLocationSequenceComponent(BaseModel): + """Offset location sequence component for a labware on another labware.""" + + kind: Literal["onLabware"] = "onLabware" + labwareUri: str = Field( + ..., + description="The definition URI of a labware that a labware can be loaded onto.", + ) + + +class OnModuleOffsetLocationSequenceComponent(BaseModel): + """Offset location sequence component for a labware on a module.""" + + kind: Literal["onModule"] = "onModule" + moduleModel: ModuleModel = Field( + ..., description="The model of a module that a lwbare can be loaded on to." + ) + + +class OnAddressableAreaOffsetLocationSequenceComponent(BaseModel): + """Offset location sequence component for a labware on an addressable area.""" + + kind: Literal["onAddressableArea"] = "onAddressableArea" + addressableAreaName: str = Field( + ..., + description=( + 'The ID of an addressable area that a labware or module can be loaded onto, such as (on the OT-2) "2" ' + 'or (on the Flex) "C1". ' + "\n\n" + "On the Flex, this field must be correct for the kind of entity it hosts. For instance, if the prior entity " + "in the location sequence is an `OnModuleOffsetLocationSequenceComponent(moduleModel=temperatureModuleV2)`, " + "this entity must be temperatureModuleV2NN where NN is the slot name in which the module resides. " + ), + ) + + +LabwareOffsetLocationSequenceComponents = ( + OnLabwareOffsetLocationSequenceComponent + | OnModuleOffsetLocationSequenceComponent + | OnAddressableAreaOffsetLocationSequenceComponent +) + +LabwareOffsetLocationSequence = list[LabwareOffsetLocationSequenceComponents] + + +class LegacyLabwareOffsetLocation(BaseModel): """Parameters describing when a given offset may apply to a given labware load.""" slotName: DeckSlotName = Field( diff --git a/api/src/opentrons/protocol_engine/types/location.py b/api/src/opentrons/protocol_engine/types/location.py index 5397b17cfeb..cc174f4bdea 100644 --- a/api/src/opentrons/protocol_engine/types/location.py +++ b/api/src/opentrons/protocol_engine/types/location.py @@ -13,7 +13,7 @@ class DeckSlotLocation(BaseModel): slotName: DeckSlotName = Field( ..., description=( - # This description should be kept in sync with LabwareOffsetLocation.slotName. + # This description should be kept in sync with LegacyLabwareOffsetLocation.slotName. "A slot on the robot's deck." "\n\n" 'The plain numbers like `"5"` are for the OT-2,' @@ -33,7 +33,7 @@ class StagingSlotLocation(BaseModel): slotName: StagingSlotName = Field( ..., description=( - # This description should be kept in sync with LabwareOffsetLocation.slotName. + # This description should be kept in sync with LegacyLabwareOffsetLocation.slotName. "A slot on the robot's staging area." "\n\n" "These apply only to the Flex. The OT-2 has no staging slots." @@ -77,6 +77,45 @@ class OnLabwareLocation(BaseModel): OFF_DECK_LOCATION: _OffDeckLocationType = "offDeck" SYSTEM_LOCATION: _SystemLocationType = "systemLocation" + +class OnLabwareLocationSequenceComponent(BaseModel): + """Labware on another labware.""" + + kind: Literal["onLabware"] = "onLabware" + labwareId: str + lidId: str | None + + +class OnModuleLocationSequenceComponent(BaseModel): + """Labware on a module.""" + + kind: Literal["onModule"] = "onModule" + moduleId: str + + +class OnAddressableAreaLocationSequenceComponent(BaseModel): + """Labware on an addressable area.""" + + kind: Literal["onAddressableArea"] = "onAddressableArea" + addressableAreaName: str + slotName: str | None + + +class NotOnDeckLocationSequenceComponent(BaseModel): + """Labware on a system location.""" + + kind: Literal["notOnDeck"] = "notOnDeck" + logicalLocationName: _OffDeckLocationType | _SystemLocationType + + +LabwareLocationSequence = list[ + OnLabwareLocationSequenceComponent + | OnModuleLocationSequenceComponent + | OnAddressableAreaLocationSequenceComponent + | NotOnDeckLocationSequenceComponent +] +"""Labware location specifier.""" + LabwareLocation = Union[ DeckSlotLocation, ModuleLocation, diff --git a/api/src/opentrons/protocol_runner/run_orchestrator.py b/api/src/opentrons/protocol_runner/run_orchestrator.py index 28266a9c485..b45d8b9db94 100644 --- a/api/src/opentrons/protocol_runner/run_orchestrator.py +++ b/api/src/opentrons/protocol_runner/run_orchestrator.py @@ -32,6 +32,7 @@ PostRunHardwareState, EngineStatus, LabwareOffsetCreate, + LegacyLabwareOffsetCreate, LabwareOffset, DeckConfigurationType, RunTimeParameter, @@ -346,7 +347,9 @@ def run_has_stopped(self) -> bool: """Get whether the run has stopped.""" return self._protocol_engine.state_view.commands.get_is_stopped() - def add_labware_offset(self, request: LabwareOffsetCreate) -> LabwareOffset: + def add_labware_offset( + self, request: LabwareOffsetCreate | LegacyLabwareOffsetCreate + ) -> LabwareOffset: """Add a new labware offset to state.""" return self._protocol_engine.add_labware_offset(request) diff --git a/api/tests/opentrons/protocol_api/core/engine/test_labware_core.py b/api/tests/opentrons/protocol_api/core/engine/test_labware_core.py index beca8fe99d1..06c2445d79e 100644 --- a/api/tests/opentrons/protocol_api/core/engine/test_labware_core.py +++ b/api/tests/opentrons/protocol_api/core/engine/test_labware_core.py @@ -23,8 +23,9 @@ from opentrons.protocol_engine.errors import LabwareNotOnDeckError from opentrons.protocol_engine.types import ( LabwareOffsetCreate, - LabwareOffsetLocation, + LabwareOffsetLocationSequence, LabwareOffsetVector, + OnAddressableAreaOffsetLocationSequenceComponent, ) from opentrons.protocol_api._liquid import Liquid from opentrons.protocol_api.core.labware import LabwareLoadParams @@ -106,16 +107,18 @@ def test_set_calibration_succeeds_in_ok_location( decoy.when( mock_engine_client.state.labware.get_display_name("cool-labware") ).then_return("what a cool labware") - location = LabwareOffsetLocation(slotName=DeckSlotName.SLOT_C2) + location = [ + OnAddressableAreaOffsetLocationSequenceComponent(addressableAreaName="C2") + ] decoy.when( mock_engine_client.state.geometry.get_offset_location("cool-labware") - ).then_return(location) + ).then_return(cast(LabwareOffsetLocationSequence, location)) subject.set_calibration(Point(1, 2, 3)) decoy.verify( mock_engine_client.add_labware_offset( LabwareOffsetCreate( definitionUri="hello/world/42", - location=location, + locationSequence=cast(LabwareOffsetLocationSequence, location), vector=LabwareOffsetVector(x=1, y=2, z=3), ) ), diff --git a/api/tests/opentrons/protocol_api/core/legacy/test_labware_offset_provider.py b/api/tests/opentrons/protocol_api/core/legacy/test_labware_offset_provider.py index 1cf0bb360fb..a31abe5b06b 100644 --- a/api/tests/opentrons/protocol_api/core/legacy/test_labware_offset_provider.py +++ b/api/tests/opentrons/protocol_api/core/legacy/test_labware_offset_provider.py @@ -12,7 +12,7 @@ ProtocolEngine, LabwareOffset, LabwareOffsetVector, - LabwareOffsetLocation, + LegacyLabwareOffsetLocation, ModuleModel, ) from opentrons.protocol_engine.state.labware import LabwareView @@ -47,9 +47,9 @@ def test_find_something( ) -> None: """It should pass along simplified labware offset info from Protocol Engine.""" decoy.when( - labware_view.find_applicable_labware_offset( + labware_view.find_applicable_labware_offset_by_legacy_location( definition_uri="some_namespace/some_load_name/123", - location=LabwareOffsetLocation( + location=LegacyLabwareOffsetLocation( slotName=DeckSlotName.SLOT_1, moduleModel=ModuleModel.TEMPERATURE_MODULE_V1, ), @@ -61,7 +61,7 @@ def test_find_something( vector=LabwareOffsetVector(x=1, y=2, z=3), # Shouldn't matter; subject should throw these away: definitionUri="result_definition_uri_should_not_matter", - location=LabwareOffsetLocation(slotName=DeckSlotName.SLOT_11), + location=LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_11), createdAt=datetime(year=2021, month=1, day=1), ) ) @@ -82,12 +82,14 @@ def test_find_nothing( subject: LabwareOffsetProvider, labware_view: LabwareView, decoy: Decoy ) -> None: """It should return a zero offset when Protocol Engine has no offset to provide.""" - decoy_call_rehearsal = labware_view.find_applicable_labware_offset( - definition_uri="some_namespace/some_load_name/123", - location=LabwareOffsetLocation( - slotName=DeckSlotName.SLOT_1, - moduleModel=ModuleModel.TEMPERATURE_MODULE_V1, - ), + decoy_call_rehearsal = ( + labware_view.find_applicable_labware_offset_by_legacy_location( + definition_uri="some_namespace/some_load_name/123", + location=LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_1, + moduleModel=ModuleModel.TEMPERATURE_MODULE_V1, + ), + ) ) decoy.when(decoy_call_rehearsal).then_return(None) diff --git a/api/tests/opentrons/protocol_engine/execution/test_equipment_handler.py b/api/tests/opentrons/protocol_engine/execution/test_equipment_handler.py index 5d3edc307bd..29c1eaa6d35 100644 --- a/api/tests/opentrons/protocol_engine/execution/test_equipment_handler.py +++ b/api/tests/opentrons/protocol_engine/execution/test_equipment_handler.py @@ -33,7 +33,10 @@ LoadedPipette, LabwareOffset, LabwareOffsetVector, - LabwareOffsetLocation, + LegacyLabwareOffsetLocation, + OnAddressableAreaOffsetLocationSequenceComponent, + OnModuleOffsetLocationSequenceComponent, + OnLabwareOffsetLocationSequenceComponent, ModuleModel, ModuleDefinition, OFF_DECK_LOCATION, @@ -231,18 +234,34 @@ async def test_load_labware( version=1, ) ).then_return(minimal_labware_def) + decoy.when( + state_store.geometry.get_projected_offset_location( + DeckSlotLocation(slotName=DeckSlotName.SLOT_3) + ) + ).then_return( + [OnAddressableAreaOffsetLocationSequenceComponent(addressableAreaName="3")] + ) decoy.when( state_store.labware.find_applicable_labware_offset( definition_uri="opentrons-test/load-name/1", - location=LabwareOffsetLocation(slotName=DeckSlotName.SLOT_3), + location=[ + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="3" + ) + ], ) ).then_return( LabwareOffset( id="labware-offset-id", createdAt=datetime(year=2021, month=1, day=2), definitionUri="opentrons-test/load-name/1", - location=LabwareOffsetLocation(slotName=DeckSlotName.SLOT_3), + location=LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_3), + locationSequence=[ + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="3" + ) + ], vector=LabwareOffsetVector(x=1, y=2, z=3), ) ) @@ -312,11 +331,21 @@ async def test_load_labware_uses_provided_id( version=1, ) ).then_return(minimal_labware_def) - + decoy.when( + state_store.geometry.get_projected_offset_location( + DeckSlotLocation(slotName=DeckSlotName.SLOT_3) + ) + ).then_return( + [OnAddressableAreaOffsetLocationSequenceComponent(addressableAreaName="3")] + ) decoy.when( state_store.labware.find_applicable_labware_offset( definition_uri="opentrons-test/load-name/1", - location=LabwareOffsetLocation(slotName=DeckSlotName.SLOT_3), + location=[ + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="3" + ) + ], ) ).then_return(None) @@ -354,10 +383,22 @@ async def test_load_labware_uses_loaded_labware_def( minimal_labware_def ) + decoy.when( + state_store.geometry.get_projected_offset_location( + DeckSlotLocation(slotName=DeckSlotName.SLOT_3) + ) + ).then_return( + [OnAddressableAreaOffsetLocationSequenceComponent(addressableAreaName="3")] + ) + decoy.when( state_store.labware.find_applicable_labware_offset( definition_uri="opentrons-test/load-name/1", - location=LabwareOffsetLocation(slotName=DeckSlotName.SLOT_3), + location=[ + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="3" + ) + ], ) ).then_return(None) @@ -406,23 +447,48 @@ async def test_load_labware_on_module( DeckSlotLocation(slotName=DeckSlotName.SLOT_3) ) + decoy.when( + state_store.geometry.get_projected_offset_location( + ModuleLocation(moduleId="module-id") + ) + ).then_return( + [ + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.THERMOCYCLER_MODULE_V1 + ), + OnAddressableAreaOffsetLocationSequenceComponent(addressableAreaName="1"), + ] + ) + decoy.when( state_store.labware.find_applicable_labware_offset( definition_uri="opentrons-test/load-name/1", - location=LabwareOffsetLocation( - slotName=DeckSlotName.SLOT_3, - moduleModel=ModuleModel.THERMOCYCLER_MODULE_V1, - ), + location=[ + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.THERMOCYCLER_MODULE_V1 + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="1" + ), + ], ) ).then_return( LabwareOffset( id="labware-offset-id", createdAt=datetime(year=2021, month=1, day=2), definitionUri="opentrons-test/load-name/1", - location=LabwareOffsetLocation( + location=LegacyLabwareOffsetLocation( slotName=DeckSlotName.SLOT_3, moduleModel=ModuleModel.THERMOCYCLER_MODULE_V1, ), + locationSequence=[ + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.THERMOCYCLER_MODULE_V1 + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="1" + ), + ], vector=LabwareOffsetVector(x=1, y=2, z=3), ) ) @@ -448,23 +514,38 @@ def test_find_offset_id_of_labware_on_deck_slot( subject: EquipmentHandler, ) -> None: """It should find the offset by resolving the provided location.""" + decoy.when( + state_store.geometry.get_projected_offset_location( + DeckSlotLocation(slotName=DeckSlotName.SLOT_3) + ) + ).then_return( + [ + OnAddressableAreaOffsetLocationSequenceComponent(addressableAreaName="3"), + ] + ) decoy.when( state_store.labware.find_applicable_labware_offset( definition_uri="opentrons-test/load-name/1", - location=LabwareOffsetLocation( - slotName=DeckSlotName.SLOT_3, - moduleModel=None, - ), + location=[ + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="3" + ) + ], ) ).then_return( LabwareOffset( id="labware-offset-id", createdAt=datetime(year=2021, month=1, day=2), definitionUri="opentrons-test/load-name/1", - location=LabwareOffsetLocation( + location=LegacyLabwareOffsetLocation( slotName=DeckSlotName.SLOT_3, moduleModel=None, ), + locationSequence=[ + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="3" + ) + ], vector=LabwareOffsetVector(x=1, y=2, z=3), ) ) @@ -490,23 +571,48 @@ def test_find_offset_id_of_labware_on_module( DeckSlotLocation(slotName=DeckSlotName.SLOT_3) ) + decoy.when( + state_store.geometry.get_projected_offset_location( + ModuleLocation(moduleId="input-module-id") + ) + ).then_return( + [ + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.THERMOCYCLER_MODULE_V1 + ), + OnAddressableAreaOffsetLocationSequenceComponent(addressableAreaName="3"), + ] + ) + decoy.when( state_store.labware.find_applicable_labware_offset( definition_uri="opentrons-test/load-name/1", - location=LabwareOffsetLocation( - slotName=DeckSlotName.SLOT_3, - moduleModel=ModuleModel.THERMOCYCLER_MODULE_V1, - ), + location=[ + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.THERMOCYCLER_MODULE_V1 + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="3" + ), + ], ) ).then_return( LabwareOffset( id="labware-offset-id", createdAt=datetime(year=2021, month=1, day=2), definitionUri="opentrons-test/load-name/1", - location=LabwareOffsetLocation( + location=LegacyLabwareOffsetLocation( slotName=DeckSlotName.SLOT_3, moduleModel=ModuleModel.THERMOCYCLER_MODULE_V1, ), + locationSequence=[ + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.THERMOCYCLER_MODULE_V1 + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="3" + ), + ], vector=LabwareOffsetVector(x=1, y=2, z=3), ) ) @@ -541,25 +647,49 @@ def test_find_offset_id_of_labware_on_labware( decoy.when(state_store.labware.get_parent_location("labware-id")).then_return( parent_location ) - + decoy.when( + state_store.geometry.get_projected_offset_location( + OnLabwareLocation(labwareId="labware-id") + ) + ).then_return( + [ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/load-name-2/1" + ), + OnAddressableAreaOffsetLocationSequenceComponent(addressableAreaName="1"), + ] + if parent_location is not OFF_DECK_LOCATION + else None + ) decoy.when( state_store.labware.find_applicable_labware_offset( definition_uri="opentrons-test/load-name-1/1", - location=LabwareOffsetLocation( - slotName=DeckSlotName.SLOT_1, - moduleModel=None, - definitionUri="opentrons-test/load-name-2/1", - ), + location=[ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/load-name-2/1" + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="1" + ), + ], ) ).then_return( LabwareOffset( id="labware-offset-id", createdAt=datetime(year=2021, month=1, day=2), definitionUri="opentrons-test/load-name/1", - location=LabwareOffsetLocation( + location=LegacyLabwareOffsetLocation( slotName=DeckSlotName.SLOT_1, definitionUri="opentrons-test/load-name-2/1", ), + locationSequence=[ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/load-name-2/1" + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="1" + ), + ], vector=LabwareOffsetVector(x=1, y=2, z=3), ) ) @@ -594,25 +724,161 @@ def test_find_offset_id_of_labware_on_labware_on_modules( DeckSlotLocation(slotName=DeckSlotName.SLOT_1) ) + decoy.when( + state_store.geometry.get_projected_offset_location( + OnLabwareLocation(labwareId="labware-id") + ) + ).then_return( + [ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/load-name-2/1" + ), + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.HEATER_SHAKER_MODULE_V1 + ), + OnAddressableAreaOffsetLocationSequenceComponent(addressableAreaName="1"), + ] + ) + decoy.when( state_store.labware.find_applicable_labware_offset( definition_uri="opentrons-test/load-name-1/1", - location=LabwareOffsetLocation( + location=[ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/load-name-2/1" + ), + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.HEATER_SHAKER_MODULE_V1 + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="1" + ), + ], + ) + ).then_return( + LabwareOffset( + id="labware-offset-id", + createdAt=datetime(year=2021, month=1, day=2), + definitionUri="opentrons-test/load-name/1", + location=LegacyLabwareOffsetLocation( slotName=DeckSlotName.SLOT_1, moduleModel=ModuleModel.HEATER_SHAKER_MODULE_V1, definitionUri="opentrons-test/load-name-2/1", ), + locationSequence=[ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/load-name-2/1" + ), + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.HEATER_SHAKER_MODULE_V1 + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="1" + ), + ], + vector=LabwareOffsetVector(x=1, y=2, z=3), + ) + ) + + result = subject.find_applicable_labware_offset_id( + labware_definition_uri="opentrons-test/load-name-1/1", + labware_location=OnLabwareLocation(labwareId="labware-id"), + ) + + assert result == "labware-offset-id" + + +def test_find_offset_id_of_labware_on_labware_on_labware_modules( + decoy: Decoy, + state_store: StateStore, + subject: EquipmentHandler, +) -> None: + """It should find an offset for a labware on a labware on a module.""" + decoy.when(state_store.labware.get_definition_uri("labware-id")).then_return( + LabwareUri("opentrons-test/load-name-2/1") + ) + + decoy.when(state_store.labware.get_parent_location("labware-id")).then_return( + ModuleLocation(moduleId="labware-id-2"), + ) + + decoy.when(state_store.labware.get_definition_uri("labware-id-2")).then_return( + LabwareUri("opentrons-test/load-name-3/1") + ) + + decoy.when(state_store.labware.get_parent_location("labware-id-2")).then_return( + ModuleLocation(moduleId="module-id"), + ) + + decoy.when(state_store.modules.get_requested_model("module-id")).then_return( + ModuleModel.HEATER_SHAKER_MODULE_V1 + ) + + decoy.when(state_store.modules.get_location("module-id")).then_return( + DeckSlotLocation(slotName=DeckSlotName.SLOT_1) + ) + + decoy.when( + state_store.geometry.get_projected_offset_location( + OnLabwareLocation(labwareId="labware-id") + ) + ).then_return( + [ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/load-name-2/1" + ), + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/load-name-3/1" + ), + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.HEATER_SHAKER_MODULE_V1 + ), + OnAddressableAreaOffsetLocationSequenceComponent(addressableAreaName="1"), + ] + ) + + decoy.when( + state_store.labware.find_applicable_labware_offset( + definition_uri="opentrons-test/load-name-1/1", + location=[ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/load-name-2/1" + ), + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/load-name-3/1" + ), + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.HEATER_SHAKER_MODULE_V1 + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="1" + ), + ], ) ).then_return( LabwareOffset( id="labware-offset-id", createdAt=datetime(year=2021, month=1, day=2), definitionUri="opentrons-test/load-name/1", - location=LabwareOffsetLocation( + location=LegacyLabwareOffsetLocation( slotName=DeckSlotName.SLOT_1, moduleModel=ModuleModel.HEATER_SHAKER_MODULE_V1, definitionUri="opentrons-test/load-name-2/1", ), + locationSequence=[ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/load-name-2/1" + ), + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/load-name-3/1" + ), + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.HEATER_SHAKER_MODULE_V1 + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="1" + ), + ], vector=LabwareOffsetVector(x=1, y=2, z=3), ) ) diff --git a/api/tests/opentrons/protocol_engine/execution/test_labware_movement_handler.py b/api/tests/opentrons/protocol_engine/execution/test_labware_movement_handler.py index 3377e39b666..ea400011b22 100644 --- a/api/tests/opentrons/protocol_engine/execution/test_labware_movement_handler.py +++ b/api/tests/opentrons/protocol_engine/execution/test_labware_movement_handler.py @@ -18,7 +18,7 @@ ModuleLocation, OnLabwareLocation, LabwareOffset, - LabwareOffsetLocation, + LegacyLabwareOffsetLocation, LabwareOffsetVector, LabwareLocation, NonStackedLocation, @@ -142,7 +142,7 @@ async def set_up_decoy_hardware_gripper( id="new-offset-id", createdAt=datetime(year=2022, month=10, day=20), definitionUri="my-labware", - location=LabwareOffsetLocation( + location=LegacyLabwareOffsetLocation( slotName=DeckSlotName.SLOT_5 ), # this location doesn't matter for this test vector=LabwareOffsetVector(x=0.5, y=0.6, z=0.7), diff --git a/api/tests/opentrons/protocol_engine/resources/test_deck_configuration_provider.py b/api/tests/opentrons/protocol_engine/resources/test_deck_configuration_provider.py index ba9c93e03cf..294266f21a8 100644 --- a/api/tests/opentrons/protocol_engine/resources/test_deck_configuration_provider.py +++ b/api/tests/opentrons/protocol_engine/resources/test_deck_configuration_provider.py @@ -1,4 +1,5 @@ """Test deck configuration provider.""" + from typing import List, Set import pytest @@ -246,7 +247,7 @@ def test_get_potential_cutout_fixtures_raises( AddressableArea( area_name="1", area_type=AreaType.SLOT, - base_slot=DeckSlotName.SLOT_A1, + base_slot=DeckSlotName.SLOT_1, display_name="Slot 1", bounding_box=Dimensions(x=128.0, y=86.0, z=0), position=AddressableOffsetVector(x=1, y=2, z=3), @@ -263,7 +264,7 @@ def test_get_potential_cutout_fixtures_raises( AddressableArea( area_name="1", area_type=AreaType.SLOT, - base_slot=DeckSlotName.SLOT_A1, + base_slot=DeckSlotName.SLOT_1, display_name="Slot 1", bounding_box=Dimensions(x=128.0, y=86.0, z=0), position=AddressableOffsetVector(x=1, y=2, z=3), @@ -280,7 +281,7 @@ def test_get_potential_cutout_fixtures_raises( AddressableArea( area_name="D1", area_type=AreaType.SLOT, - base_slot=DeckSlotName.SLOT_A1, + base_slot=DeckSlotName.SLOT_D1, display_name="Slot D1", bounding_box=Dimensions(x=128.0, y=86.0, z=0), position=AddressableOffsetVector(x=1, y=2, z=3), @@ -293,7 +294,7 @@ def test_get_potential_cutout_fixtures_raises( AddressableArea( area_name="movableTrashB3", area_type=AreaType.MOVABLE_TRASH, - base_slot=DeckSlotName.SLOT_A1, + base_slot=DeckSlotName.SLOT_B3, display_name="Trash Bin in B3", bounding_box=Dimensions(x=225, y=78, z=40), position=AddressableOffsetVector(x=-5.25, y=6, z=3), @@ -306,7 +307,7 @@ def test_get_potential_cutout_fixtures_raises( AddressableArea( area_name="gripperWasteChute", area_type=AreaType.WASTE_CHUTE, - base_slot=DeckSlotName.SLOT_A1, + base_slot=DeckSlotName.SLOT_D3, display_name="Waste Chute", bounding_box=Dimensions(x=0, y=0, z=0), position=AddressableOffsetVector(x=65, y=31, z=139.5), @@ -323,7 +324,7 @@ def test_get_addressable_area_from_name( ) -> None: """It should get the deck position for the requested cutout id.""" addressable_area = subject.get_addressable_area_from_name( - addressable_area_name, DeckPoint(x=1, y=2, z=3), DeckSlotName.SLOT_A1, deck_def + addressable_area_name, DeckPoint(x=1, y=2, z=3), deck_def ) assert addressable_area == expected_addressable_area @@ -336,6 +337,5 @@ def test_get_addressable_area_from_name_raises( subject.get_addressable_area_from_name( "theFunArea", DeckPoint(x=1, y=2, z=3), - DeckSlotName.SLOT_A1, ot3_standard_deck_def, ) diff --git a/api/tests/opentrons/protocol_engine/state/test_addressable_area_view_old.py b/api/tests/opentrons/protocol_engine/state/test_addressable_area_view_old.py index 5aa157c59db..a85f51a1891 100644 --- a/api/tests/opentrons/protocol_engine/state/test_addressable_area_view_old.py +++ b/api/tests/opentrons/protocol_engine/state/test_addressable_area_view_old.py @@ -214,7 +214,6 @@ def test_get_addressable_area_for_simulation_not_loaded(decoy: Decoy) -> None: deck_configuration_provider.get_addressable_area_from_name( "abc", DeckPoint(x=1, y=2, z=3), - DeckSlotName.SLOT_A1, sentinel.deck_definition, ) ).then_return(addressable_area) diff --git a/api/tests/opentrons/protocol_engine/state/test_geometry_view.py b/api/tests/opentrons/protocol_engine/state/test_geometry_view.py index f5f86fc8c4c..3c214923e25 100644 --- a/api/tests/opentrons/protocol_engine/state/test_geometry_view.py +++ b/api/tests/opentrons/protocol_engine/state/test_geometry_view.py @@ -65,6 +65,9 @@ ProbedVolumeInfo, LoadedVolumeInfo, WellLiquidInfo, + OnAddressableAreaOffsetLocationSequenceComponent, + OnModuleOffsetLocationSequenceComponent, + OnLabwareOffsetLocationSequenceComponent, ) from opentrons.protocol_engine.commands import ( CommandStatus, @@ -3042,10 +3045,9 @@ def test_get_offset_location_deck_slot( ) labware_store.handle_action(action) offset_location = subject.get_offset_location("labware-id-1") - assert offset_location is not None - assert offset_location.slotName == DeckSlotName.SLOT_C2 - assert offset_location.definitionUri is None - assert offset_location.moduleModel is None + assert offset_location == [ + OnAddressableAreaOffsetLocationSequenceComponent(addressableAreaName="C2") + ] @pytest.mark.parametrize("use_mocks", [False]) @@ -3062,7 +3064,7 @@ def test_get_offset_location_module( command=LoadModule( params=LoadModuleParams( location=DeckSlotLocation(slotName=DeckSlotName.SLOT_A3), - model=ModuleModel.TEMPERATURE_MODULE_V1, + model=ModuleModel.TEMPERATURE_MODULE_V2, ), id="load-module-1", createdAt=datetime.now(), @@ -3107,10 +3109,14 @@ def test_get_offset_location_module( module_store.handle_action(load_module) labware_store.handle_action(load_labware) offset_location = subject.get_offset_location("labware-id-1") - assert offset_location is not None - assert offset_location.slotName == DeckSlotName.SLOT_A3 - assert offset_location.definitionUri is None - assert offset_location.moduleModel == ModuleModel.TEMPERATURE_MODULE_V1 + assert offset_location == [ + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2 + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="temperatureModuleV2A3" + ), + ] @pytest.mark.parametrize("use_mocks", [False]) @@ -3128,8 +3134,8 @@ def test_get_offset_location_module_with_adapter( load_module = SucceedCommandAction( command=LoadModule( params=LoadModuleParams( - location=DeckSlotLocation(slotName=DeckSlotName.SLOT_A2), - model=ModuleModel.TEMPERATURE_MODULE_V1, + location=DeckSlotLocation(slotName=DeckSlotName.SLOT_A3), + model=ModuleModel.TEMPERATURE_MODULE_V2, ), id="load-module-1", createdAt=datetime.now(), @@ -3202,12 +3208,17 @@ def test_get_offset_location_module_with_adapter( labware_store.handle_action(load_adapter) labware_store.handle_action(load_labware) offset_location = subject.get_offset_location("labware-id-1") - assert offset_location is not None - assert offset_location.slotName == DeckSlotName.SLOT_A2 - assert offset_location.definitionUri == labware_view.get_uri_from_definition( - nice_adapter_definition - ) - assert offset_location.moduleModel == ModuleModel.TEMPERATURE_MODULE_V1 + assert offset_location == [ + OnLabwareOffsetLocationSequenceComponent( + labwareUri=labware_view.get_uri_from_definition(nice_adapter_definition) + ), + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2 + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="temperatureModuleV2A3" + ), + ] @pytest.mark.parametrize("use_mocks", [False]) diff --git a/api/tests/opentrons/protocol_engine/state/test_labware_store_old.py b/api/tests/opentrons/protocol_engine/state/test_labware_store_old.py index d5e7e41770e..75e3aeb7339 100644 --- a/api/tests/opentrons/protocol_engine/state/test_labware_store_old.py +++ b/api/tests/opentrons/protocol_engine/state/test_labware_store_old.py @@ -4,6 +4,7 @@ longer helpful. Try to add new tests to test_labware_state.py, where they can be tested together, treating LabwareState as a private implementation detail. """ + from typing import Optional from opentrons.protocol_engine.state import update_types import pytest @@ -17,9 +18,10 @@ from opentrons.protocol_engine.types import ( LabwareOffset, - LabwareOffsetCreate, + LabwareOffsetCreateInternal, LabwareOffsetVector, - LabwareOffsetLocation, + LegacyLabwareOffsetLocation, + OnAddressableAreaOffsetLocationSequenceComponent, DeckSlotLocation, LoadedLabware, OFF_DECK_LOCATION, @@ -64,9 +66,12 @@ def test_handles_add_labware_offset( subject: LabwareStore, ) -> None: """It should add the labware offset to the state and add the ID.""" - request = LabwareOffsetCreate( + request = LabwareOffsetCreateInternal( definitionUri="offset-definition-uri", - location=LabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + legacyLocation=LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + locationSequence=[ + OnAddressableAreaOffsetLocationSequenceComponent(addressableAreaName="1") + ], vector=LabwareOffsetVector(x=1, y=2, z=3), ) @@ -74,7 +79,10 @@ def test_handles_add_labware_offset( id="offset-id", createdAt=datetime(year=2021, month=1, day=2), definitionUri="offset-definition-uri", - location=LabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + location=LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + locationSequence=[ + OnAddressableAreaOffsetLocationSequenceComponent(addressableAreaName="1") + ], vector=LabwareOffsetVector(x=1, y=2, z=3), ) @@ -99,9 +107,12 @@ def test_handles_load_labware( offset_id: Optional[str], ) -> None: """It should add the labware data to the state.""" - offset_request = LabwareOffsetCreate( + offset_request = LabwareOffsetCreateInternal( definitionUri="offset-definition-uri", - location=LabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + legacyLocation=LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + locationSequence=[ + OnAddressableAreaOffsetLocationSequenceComponent(addressableAreaName="1") + ], vector=LabwareOffsetVector(x=1, y=2, z=3), ) @@ -180,9 +191,12 @@ def test_handles_reload_labware( == expected_definition_uri ) - offset_request = LabwareOffsetCreate( + offset_request = LabwareOffsetCreateInternal( definitionUri="offset-definition-uri", - location=LabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + legacyLocation=LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + locationSequence=[ + OnAddressableAreaOffsetLocationSequenceComponent(addressableAreaName="1") + ], vector=LabwareOffsetVector(x=1, y=2, z=3), ) subject.handle_action( @@ -242,9 +256,12 @@ def test_handles_move_labware( ) -> None: """It should update labware state with new location & offset.""" comment_command = create_comment_command() - offset_request = LabwareOffsetCreate( + offset_request = LabwareOffsetCreateInternal( definitionUri="offset-definition-uri", - location=LabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + legacyLocation=LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + locationSequence=[ + OnAddressableAreaOffsetLocationSequenceComponent(addressableAreaName="1") + ], vector=LabwareOffsetVector(x=1, y=2, z=3), ) subject.handle_action( @@ -297,9 +314,12 @@ def test_handles_move_labware_off_deck( ) -> None: """It should update labware state with new location & offset.""" comment_command = create_comment_command() - offset_request = LabwareOffsetCreate( + offset_request = LabwareOffsetCreateInternal( definitionUri="offset-definition-uri", - location=LabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + legacyLocation=LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + locationSequence=[ + OnAddressableAreaOffsetLocationSequenceComponent(addressableAreaName="1") + ], vector=LabwareOffsetVector(x=1, y=2, z=3), ) subject.handle_action( diff --git a/api/tests/opentrons/protocol_engine/state/test_labware_view_old.py b/api/tests/opentrons/protocol_engine/state/test_labware_view_old.py index 770f24f3e7f..699893b47b4 100644 --- a/api/tests/opentrons/protocol_engine/state/test_labware_view_old.py +++ b/api/tests/opentrons/protocol_engine/state/test_labware_view_old.py @@ -4,6 +4,7 @@ longer helpful. Try to add new tests to test_labware_state.py, where they can be tested together, treating LabwareState as a private implementation detail. """ + import pytest from datetime import datetime from typing import Dict, Optional, cast, ContextManager, Any, Union, NamedTuple, List @@ -34,7 +35,7 @@ Dimensions, LabwareOffset, LabwareOffsetVector, - LabwareOffsetLocation, + LegacyLabwareOffsetLocation, LoadedLabware, ModuleModel, ModuleLocation, @@ -44,6 +45,8 @@ OFF_DECK_LOCATION, OverlapOffset, LabwareMovementOffsetData, + OnAddressableAreaOffsetLocationSequenceComponent, + OnModuleOffsetLocationSequenceComponent, ) from opentrons.protocol_engine.state._move_types import EdgePathType from opentrons.protocol_engine.state.labware import ( @@ -838,7 +841,10 @@ def test_get_labware_offset_vector() -> None: id="offset-id", createdAt=datetime(year=2021, month=1, day=2), definitionUri="some-labware-uri", - location=LabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + location=LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + locationSequence=[ + OnAddressableAreaOffsetLocationSequenceComponent(addressableAreaName="1") + ], vector=offset_vector, ) @@ -866,7 +872,10 @@ def test_get_labware_offset() -> None: id="id-a", createdAt=datetime(year=2021, month=1, day=1), definitionUri="uri-a", - location=LabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + location=LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + locationSequence=[ + OnAddressableAreaOffsetLocationSequenceComponent(addressableAreaName="1") + ], vector=LabwareOffsetVector(x=1, y=1, z=1), ) @@ -874,7 +883,10 @@ def test_get_labware_offset() -> None: id="id-b", createdAt=datetime(year=2022, month=2, day=2), definitionUri="uri-b", - location=LabwareOffsetLocation(slotName=DeckSlotName.SLOT_2), + location=LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_2), + locationSequence=[ + OnAddressableAreaOffsetLocationSequenceComponent(addressableAreaName="2") + ], vector=LabwareOffsetVector(x=2, y=2, z=2), ) @@ -894,7 +906,10 @@ def test_get_labware_offsets() -> None: id="id-a", createdAt=datetime(year=2021, month=1, day=1), definitionUri="uri-a", - location=LabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + location=LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + locationSequence=[ + OnAddressableAreaOffsetLocationSequenceComponent(addressableAreaName="1") + ], vector=LabwareOffsetVector(x=1, y=1, z=1), ) @@ -902,7 +917,10 @@ def test_get_labware_offsets() -> None: id="id-b", createdAt=datetime(year=2022, month=2, day=2), definitionUri="uri-b", - location=LabwareOffsetLocation(slotName=DeckSlotName.SLOT_2), + location=LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_2), + locationSequence=[ + OnAddressableAreaOffsetLocationSequenceComponent(addressableAreaName="2") + ], vector=LabwareOffsetVector(x=2, y=2, z=2), ) @@ -926,7 +944,10 @@ def test_find_applicable_labware_offset() -> None: id="id-1", createdAt=datetime(year=2021, month=1, day=1), definitionUri="definition-uri", - location=LabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + location=LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + locationSequence=[ + OnAddressableAreaOffsetLocationSequenceComponent(addressableAreaName="1") + ], vector=LabwareOffsetVector(x=1, y=1, z=1), ) @@ -935,7 +956,10 @@ def test_find_applicable_labware_offset() -> None: id="id-2", createdAt=datetime(year=2022, month=2, day=2), definitionUri="definition-uri", - location=LabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + location=LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + locationSequence=[ + OnAddressableAreaOffsetLocationSequenceComponent(addressableAreaName="1") + ], vector=LabwareOffsetVector(x=2, y=2, z=2), ) @@ -943,10 +967,16 @@ def test_find_applicable_labware_offset() -> None: id="id-3", createdAt=datetime(year=2023, month=3, day=3), definitionUri="on-module-definition-uri", - location=LabwareOffsetLocation( + location=LegacyLabwareOffsetLocation( slotName=DeckSlotName.SLOT_1, moduleModel=ModuleModel.TEMPERATURE_MODULE_V1, ), + locationSequence=[ + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.TEMPERATURE_MODULE_V1 + ), + OnAddressableAreaOffsetLocationSequenceComponent(addressableAreaName="1"), + ], vector=LabwareOffsetVector(x=3, y=3, z=3), ) @@ -959,7 +989,11 @@ def test_find_applicable_labware_offset() -> None: assert ( subject.find_applicable_labware_offset( definition_uri="definition-uri", - location=LabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + location=[ + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="1" + ) + ], ) == offset_2 ) @@ -967,10 +1001,14 @@ def test_find_applicable_labware_offset() -> None: assert ( subject.find_applicable_labware_offset( definition_uri="on-module-definition-uri", - location=LabwareOffsetLocation( - slotName=DeckSlotName.SLOT_1, - moduleModel=ModuleModel.TEMPERATURE_MODULE_V1, - ), + location=[ + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.TEMPERATURE_MODULE_V1 + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="1" + ), + ], ) == offset_3 ) @@ -979,7 +1017,11 @@ def test_find_applicable_labware_offset() -> None: assert ( subject.find_applicable_labware_offset( definition_uri="different-definition-uri", - location=LabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + location=[ + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="1" + ) + ], ) is None ) @@ -988,7 +1030,11 @@ def test_find_applicable_labware_offset() -> None: assert ( subject.find_applicable_labware_offset( definition_uri="different-definition-uri", - location=LabwareOffsetLocation(slotName=DeckSlotName.SLOT_2), + location=[ + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="2" + ) + ], ) is None ) diff --git a/api/tests/opentrons/protocol_engine/test_labware_offset_standardization.py b/api/tests/opentrons/protocol_engine/test_labware_offset_standardization.py new file mode 100644 index 00000000000..f78885a8428 --- /dev/null +++ b/api/tests/opentrons/protocol_engine/test_labware_offset_standardization.py @@ -0,0 +1,725 @@ +"""Tests for `labware_offset_standardization`.""" + +from functools import lru_cache +import pytest + +from opentrons_shared_data.robot.types import RobotType +from opentrons_shared_data.deck import load +from opentrons_shared_data.deck.types import DeckDefinitionV5 +from opentrons.types import DeckSlotName +from opentrons.protocol_engine import labware_offset_standardization as subject +from opentrons.protocol_engine.types import ( + LabwareOffsetCreate, + LegacyLabwareOffsetCreate, + LegacyLabwareOffsetLocation, + OnLabwareOffsetLocationSequenceComponent, + OnModuleOffsetLocationSequenceComponent, + OnAddressableAreaOffsetLocationSequenceComponent, + ModuleModel, + LabwareOffsetVector, + LabwareOffsetLocationSequence, + LabwareOffsetCreateInternal, +) + + +@lru_cache +def load_from_robot_type(robot_type: RobotType) -> DeckDefinitionV5: + """Get a deck from robot type.""" + if robot_type == "OT-3 Standard": + return load("ot3_standard") + else: + return load("ot2_standard") + + +@pytest.mark.parametrize( + ("location", "robot_type", "expected_modern_location", "expected_legacy_location"), + [ + # Directly on a slot + pytest.param( + LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_5), + "OT-2 Standard", + [OnAddressableAreaOffsetLocationSequenceComponent(addressableAreaName="5")], + LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_5), + id="direct-slot-ot2-native", + ), + pytest.param( + LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_5), + "OT-3 Standard", + [ + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="C2" + ) + ], + LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_C2), + id="direct-slot-flex-ot2", + ), + pytest.param( + LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_C2), + "OT-2 Standard", + [OnAddressableAreaOffsetLocationSequenceComponent(addressableAreaName="5")], + LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_5), + id="direct-slot-ot2-flex", + ), + pytest.param( + LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_C2), + "OT-3 Standard", + [ + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="C2" + ) + ], + LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_C2), + id="direct-slot-flex-native", + ), + # On a module with no adapter + pytest.param( + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_D1, + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + "OT-3 Standard", + [ + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2 + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="temperatureModuleV2D1", + ), + ], + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_D1, + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + id="module-flex-native", + ), + pytest.param( + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_1, + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + "OT-3 Standard", + [ + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2 + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="temperatureModuleV2D1", + ), + ], + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_D1, + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + id="module-flex-ot2", + ), + pytest.param( + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_D1, + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + "OT-2 Standard", + [ + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="1", + ), + ], + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_1, + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + id="module-ot2-flex", + ), + pytest.param( + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_1, + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + "OT-2 Standard", + [ + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="1", + ), + ], + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_1, + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + id="module-ot2-native", + ), + # On a labware (or stack...) on a slot + pytest.param( + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_D1, definitionUri="opentrons-test/foo/1" + ), + "OT-3 Standard", + [ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/foo/1" + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="D1" + ), + ], + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_D1, definitionUri="opentrons-test/foo/1" + ), + id="labware-slot-flex-native", + ), + pytest.param( + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_D1, definitionUri="opentrons-test/foo/1" + ), + "OT-2 Standard", + [ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/foo/1" + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="1" + ), + ], + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_1, definitionUri="opentrons-test/foo/1" + ), + id="labware-slot-ot2-flex", + ), + pytest.param( + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_1, definitionUri="opentrons-test/foo/1" + ), + "OT-3 Standard", + [ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/foo/1" + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="D1" + ), + ], + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_D1, definitionUri="opentrons-test/foo/1" + ), + id="labware-slot-flex-ot2", + ), + pytest.param( + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_1, definitionUri="opentrons-test/foo/1" + ), + "OT-2 Standard", + [ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/foo/1" + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="1" + ), + ], + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_1, definitionUri="opentrons-test/foo/1" + ), + id="labware-slot-ot2-native", + ), + # On an adapter on a module + pytest.param( + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_D1, + definitionUri="opentrons-test/foo/1", + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + "OT-3 Standard", + [ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/foo/1" + ), + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="temperatureModuleV2D1", + ), + ], + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_D1, + definitionUri="opentrons-test/foo/1", + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + id="labware-module-flex-native", + ), + pytest.param( + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_D1, + definitionUri="opentrons-test/foo/1", + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + "OT-2 Standard", + [ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/foo/1" + ), + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="1", + ), + ], + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_1, + definitionUri="opentrons-test/foo/1", + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + id="labware-module-ot2-flex", + ), + pytest.param( + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_1, + definitionUri="opentrons-test/foo/1", + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + "OT-3 Standard", + [ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/foo/1" + ), + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="temperatureModuleV2D1", + ), + ], + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_D1, + definitionUri="opentrons-test/foo/1", + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + id="labware-module-flex-ot2", + ), + pytest.param( + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_1, + definitionUri="opentrons-test/foo/1", + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + "OT-2 Standard", + [ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/foo/1" + ), + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="1", + ), + ], + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_1, + definitionUri="opentrons-test/foo/1", + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + id="labware-module-ot2-native", + ), + ], +) +def test_standardize_legacy_labware_offset( + location: LegacyLabwareOffsetLocation, + robot_type: RobotType, + expected_modern_location: LabwareOffsetLocationSequence, + expected_legacy_location: LegacyLabwareOffsetLocation, +) -> None: + """It should convert deck slots in `LegacyLabwareOffsetCreate`s and go to the new format.""" + deck_def = load_from_robot_type(robot_type) + original = LegacyLabwareOffsetCreate( + definitionUri="opentrons-test/foo/1", + location=location, + vector=LabwareOffsetVector(x=1, y=2, z=3), + ) + expected = LabwareOffsetCreateInternal( + definitionUri="opentrons-test/foo/1", + legacyLocation=expected_legacy_location, + locationSequence=expected_modern_location, + vector=LabwareOffsetVector(x=1, y=2, z=3), + ) + assert ( + subject.standardize_labware_offset_create(original, robot_type, deck_def) + == expected + ) + + +@pytest.mark.parametrize( + ("location", "robot_type", "expected_modern_location", "expected_legacy_location"), + [ + # Directly on a slot + pytest.param( + [OnAddressableAreaOffsetLocationSequenceComponent(addressableAreaName="5")], + "OT-2 Standard", + [OnAddressableAreaOffsetLocationSequenceComponent(addressableAreaName="5")], + LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_5), + id="slot-direct-ot2", + ), + pytest.param( + [ + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="C2" + ) + ], + "OT-3 Standard", + [ + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="C2" + ) + ], + LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_C2), + id="slot-direct-flex", + ), + # On a module with no adapter + pytest.param( + [ + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="temperatureModuleV2D1", + ), + ], + "OT-3 Standard", + [ + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="temperatureModuleV2D1", + ), + ], + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_D1, + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + id="module-slot-flex", + ), + pytest.param( + [ + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="1", + ), + ], + "OT-2 Standard", + [ + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="1", + ), + ], + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_1, + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + id="module-slot-ot2", + ), + # On a labware on a slot + pytest.param( + [ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/foo/1" + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="D1" + ), + ], + "OT-3 Standard", + [ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/foo/1" + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="D1" + ), + ], + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_D1, definitionUri="opentrons-test/foo/1" + ), + id="labware-slot-flex", + ), + pytest.param( + [ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/foo/1" + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="1" + ), + ], + "OT-2 Standard", + [ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/foo/1" + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="1" + ), + ], + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_1, definitionUri="opentrons-test/foo/1" + ), + id="labware-slot-ot2", + ), + # On an adapter on a module + pytest.param( + [ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/foo/1" + ), + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="temperatureModuleV2D1", + ), + ], + "OT-3 Standard", + [ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/foo/1" + ), + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="temperatureModuleV2D1", + ), + ], + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_D1, + definitionUri="opentrons-test/foo/1", + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + id="labware-module-flex", + ), + pytest.param( + [ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/foo/1" + ), + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="1", + ), + ], + "OT-2 Standard", + [ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/foo/1" + ), + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="1", + ), + ], + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_1, + definitionUri="opentrons-test/foo/1", + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + id="labware-slot-ot2", + ), + # On a stack of labware + pytest.param( + [ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/foo/1" + ), + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/bar/1" + ), + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/baz/1" + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="A3", + ), + ], + "OT-3 Standard", + [ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/foo/1" + ), + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/bar/1" + ), + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/baz/1" + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="A3", + ), + ], + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_A3, + definitionUri="opentrons-test/foo/1", + ), + id="labware-stack-flex", + ), + pytest.param( + [ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/foo/1" + ), + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/bar/1" + ), + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/baz/1" + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="2", + ), + ], + "OT-2 Standard", + [ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/foo/1" + ), + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/bar/1" + ), + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/baz/1" + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="2", + ), + ], + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_2, + definitionUri="opentrons-test/foo/1", + ), + id="labware-stack-ot2", + ), + # On a stack of labware on a module + pytest.param( + [ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/foo/1" + ), + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/bar/1" + ), + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/baz/1" + ), + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="3", + ), + ], + "OT-2 Standard", + [ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/foo/1" + ), + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/bar/1" + ), + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/baz/1" + ), + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="3", + ), + ], + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_3, + definitionUri="opentrons-test/foo/1", + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + id="labware-stack-module-ot2", + ), + pytest.param( + [ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/foo/1" + ), + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/bar/1" + ), + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/baz/1" + ), + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="A1", + ), + ], + "OT-3 Standard", + [ + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/foo/1" + ), + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/bar/1" + ), + OnLabwareOffsetLocationSequenceComponent( + labwareUri="opentrons-test/baz/1" + ), + OnModuleOffsetLocationSequenceComponent( + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="A1", + ), + ], + LegacyLabwareOffsetLocation( + slotName=DeckSlotName.SLOT_A1, + definitionUri="opentrons-test/foo/1", + moduleModel=ModuleModel.TEMPERATURE_MODULE_V2, + ), + id="labware-stack-module-flex", + ), + ], +) +def test_standardize_modern_labware_offset( + location: LabwareOffsetLocationSequence, + robot_type: RobotType, + expected_modern_location: LabwareOffsetLocationSequence, + expected_legacy_location: LegacyLabwareOffsetLocation, +) -> None: + """It should convert deck slots in `LabwareOffsetCreate`s and fill in the old format.""" + deck_def = load_from_robot_type(robot_type) + original = LabwareOffsetCreate( + definitionUri="opentrons-test/foo/1", + locationSequence=location, + vector=LabwareOffsetVector(x=1, y=2, z=3), + ) + expected = LabwareOffsetCreateInternal( + definitionUri="opentrons-test/foo/1", + legacyLocation=expected_legacy_location, + locationSequence=expected_modern_location, + vector=LabwareOffsetVector(x=1, y=2, z=3), + ) + assert ( + subject.standardize_labware_offset_create(original, robot_type, deck_def) + == expected + ) diff --git a/api/tests/opentrons/protocol_engine/test_protocol_engine.py b/api/tests/opentrons/protocol_engine/test_protocol_engine.py index 6c1efcc55d7..ed933e760d0 100644 --- a/api/tests/opentrons/protocol_engine/test_protocol_engine.py +++ b/api/tests/opentrons/protocol_engine/test_protocol_engine.py @@ -2,7 +2,7 @@ import inspect from datetime import datetime -from typing import Any +from typing import Any, cast from unittest.mock import sentinel import pytest @@ -10,6 +10,7 @@ from opentrons_shared_data.robot.types import RobotType from opentrons_shared_data.labware.labware_definition import LabwareDefinition +from opentrons_shared_data.deck.types import DeckDefinitionV5 from opentrons.protocol_engine.actions.actions import SetErrorRecoveryPolicyAction from opentrons.protocol_engine.state.update_types import StateUpdate @@ -18,7 +19,12 @@ from opentrons.hardware_control.modules import MagDeck, TempDeck from opentrons.hardware_control.types import PauseType as HardwarePauseType -from opentrons.protocol_engine import ProtocolEngine, commands, slot_standardization +from opentrons.protocol_engine import ( + ProtocolEngine, + commands, + slot_standardization, + labware_offset_standardization, +) from opentrons.protocol_engine.errors.exceptions import ( CommandNotAllowedError, ) @@ -26,8 +32,11 @@ DeckType, LabwareOffset, LabwareOffsetCreate, + LegacyLabwareOffsetCreate, LabwareOffsetVector, - LabwareOffsetLocation, + LegacyLabwareOffsetLocation, + OnAddressableAreaOffsetLocationSequenceComponent, + LabwareOffsetCreateInternal, LabwareUri, ModuleDefinition, ModuleModel, @@ -138,6 +147,17 @@ def _mock_slot_standardization_module( monkeypatch.setattr(slot_standardization, name, decoy.mock(func=func)) +@pytest.fixture(autouse=True) +def _mock_labware_offset_standardization_module( + decoy: Decoy, monkeypatch: pytest.MonkeyPatch +) -> None: + """Mock out opentrons.labware_offset_standardization functions.""" + for name, func in inspect.getmembers( + labware_offset_standardization, inspect.isfunction + ): + monkeypatch.setattr(labware_offset_standardization, name, decoy.mock(func=func)) + + @pytest.fixture(autouse=True) def _mock_hash_command_params_module( decoy: Decoy, monkeypatch: pytest.MonkeyPatch @@ -1020,6 +1040,81 @@ def test_add_plugin( decoy.verify(plugin_starter.start(plugin)) +def test_add_legacy_labware_offset( + decoy: Decoy, + action_dispatcher: ActionDispatcher, + model_utils: ModelUtils, + state_store: StateStore, + subject: ProtocolEngine, +) -> None: + """It should have the labware offset request resolved and added to state.""" + request = LegacyLabwareOffsetCreate( + definitionUri="definition-uri", + location=LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + vector=LabwareOffsetVector(x=1, y=2, z=3), + ) + + standardized_request = LabwareOffsetCreateInternal( + definitionUri="standardized-definition-uri", + locationSequence=[ + OnAddressableAreaOffsetLocationSequenceComponent(addressableAreaName="2") + ], + legacyLocation=LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_2), + vector=LabwareOffsetVector(x=2, y=3, z=4), + ) + + id = "labware-offset-id" + + created_at = datetime(year=2021, month=11, day=15) + + expected_result = LabwareOffset( + id=id, + createdAt=created_at, + definitionUri=standardized_request.definitionUri, + location=standardized_request.legacyLocation, + locationSequence=standardized_request.locationSequence, + vector=standardized_request.vector, + ) + + robot_type: RobotType = "OT-3 Standard" + decoy.when(state_store.config).then_return( + Config(robot_type=robot_type, deck_type=DeckType.OT3_STANDARD) + ) + decoy.when(state_store.addressable_areas.deck_definition).then_return( + cast(DeckDefinitionV5, {}) + ) + decoy.when( + labware_offset_standardization.standardize_labware_offset_create( + request, robot_type, cast(DeckDefinitionV5, {}) + ) + ).then_return(standardized_request) + decoy.when(model_utils.generate_id()).then_return(id) + decoy.when(model_utils.get_timestamp()).then_return(created_at) + decoy.when( + state_store.labware.get_labware_offset(labware_offset_id=id) + ).then_return(expected_result) + + result = subject.add_labware_offset( + request=LegacyLabwareOffsetCreate( + definitionUri="definition-uri", + location=LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + vector=LabwareOffsetVector(x=1, y=2, z=3), + ) + ) + + assert result == expected_result + + decoy.verify( + action_dispatcher.dispatch( + AddLabwareOffsetAction( + labware_offset_id=id, + created_at=created_at, + request=standardized_request, + ) + ) + ) + + def test_add_labware_offset( decoy: Decoy, action_dispatcher: ActionDispatcher, @@ -1030,23 +1125,31 @@ def test_add_labware_offset( """It should have the labware offset request resolved and added to state.""" request = LabwareOffsetCreate( definitionUri="definition-uri", - location=LabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + locationSequence=[ + OnAddressableAreaOffsetLocationSequenceComponent(addressableAreaName="1") + ], vector=LabwareOffsetVector(x=1, y=2, z=3), ) - standardized_request = LabwareOffsetCreate( + + standardized_request = LabwareOffsetCreateInternal( definitionUri="standardized-definition-uri", - location=LabwareOffsetLocation(slotName=DeckSlotName.SLOT_2), - vector=LabwareOffsetVector(x=2, y=3, z=4), + locationSequence=[ + OnAddressableAreaOffsetLocationSequenceComponent(addressableAreaName="3") + ], + legacyLocation=LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_3), + vector=LabwareOffsetVector(x=2, y=5, z=6), ) id = "labware-offset-id" + created_at = datetime(year=2021, month=11, day=15) expected_result = LabwareOffset( id=id, createdAt=created_at, definitionUri=standardized_request.definitionUri, - location=standardized_request.location, + location=standardized_request.legacyLocation, + locationSequence=standardized_request.locationSequence, vector=standardized_request.vector, ) @@ -1054,8 +1157,13 @@ def test_add_labware_offset( decoy.when(state_store.config).then_return( Config(robot_type=robot_type, deck_type=DeckType.OT3_STANDARD) ) + decoy.when(state_store.addressable_areas.deck_definition).then_return( + cast(DeckDefinitionV5, {}) + ) decoy.when( - slot_standardization.standardize_labware_offset(request, robot_type) + labware_offset_standardization.standardize_labware_offset_create( + request, robot_type, cast(DeckDefinitionV5, {}) + ) ).then_return(standardized_request) decoy.when(model_utils.generate_id()).then_return(id) decoy.when(model_utils.get_timestamp()).then_return(created_at) @@ -1066,7 +1174,11 @@ def test_add_labware_offset( result = subject.add_labware_offset( request=LabwareOffsetCreate( definitionUri="definition-uri", - location=LabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + locationSequence=[ + OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="1" + ) + ], vector=LabwareOffsetVector(x=1, y=2, z=3), ) ) diff --git a/api/tests/opentrons/protocol_engine/test_slot_standardization.py b/api/tests/opentrons/protocol_engine/test_slot_standardization.py index f97d09af242..78090e16b00 100644 --- a/api/tests/opentrons/protocol_engine/test_slot_standardization.py +++ b/api/tests/opentrons/protocol_engine/test_slot_standardization.py @@ -13,8 +13,6 @@ OnLabwareLocation, LabwareLocation, LabwareMovementStrategy, - LabwareOffsetCreate, - LabwareOffsetLocation, LabwareOffsetVector, ModuleLocation, ModuleModel, @@ -22,42 +20,6 @@ ) -@pytest.mark.parametrize("module_model", [None, ModuleModel.MAGNETIC_MODULE_V1]) -@pytest.mark.parametrize( - ("slot_name", "robot_type", "expected_slot_name"), - [ - (DeckSlotName.SLOT_5, "OT-2 Standard", DeckSlotName.SLOT_5), - (DeckSlotName.SLOT_C2, "OT-2 Standard", DeckSlotName.SLOT_5), - (DeckSlotName.SLOT_5, "OT-3 Standard", DeckSlotName.SLOT_C2), - (DeckSlotName.SLOT_C2, "OT-3 Standard", DeckSlotName.SLOT_C2), - ], -) -def test_standardize_labware_offset( - module_model: ModuleModel, - slot_name: DeckSlotName, - robot_type: RobotType, - expected_slot_name: DeckSlotName, -) -> None: - """It should convert deck slots in `LabwareOffsetCreate`s.""" - original = LabwareOffsetCreate( - definitionUri="opentrons-test/foo/1", - location=LabwareOffsetLocation( - moduleModel=module_model, - slotName=slot_name, - ), - vector=LabwareOffsetVector(x=1, y=2, z=3), - ) - expected = LabwareOffsetCreate( - definitionUri="opentrons-test/foo/1", - location=LabwareOffsetLocation( - moduleModel=module_model, - slotName=expected_slot_name, - ), - vector=LabwareOffsetVector(x=1, y=2, z=3), - ) - assert subject.standardize_labware_offset(original, robot_type) == expected - - @pytest.mark.parametrize( ("original_location", "robot_type", "expected_location"), [ diff --git a/app/src/molecules/PythonLabwareOffsetSnippet/index.tsx b/app/src/molecules/PythonLabwareOffsetSnippet/index.tsx index d6e1e4bbd7d..b416858d156 100644 --- a/app/src/molecules/PythonLabwareOffsetSnippet/index.tsx +++ b/app/src/molecules/PythonLabwareOffsetSnippet/index.tsx @@ -2,7 +2,7 @@ import { useState, useEffect } from 'react' import styled from 'styled-components' import { TYPOGRAPHY, SPACING, BORDERS, COLORS } from '@opentrons/components' import { createSnippet } from './createSnippet' -import type { LabwareOffsetCreateData } from '@opentrons/api-client' +import type { LegacyLabwareOffsetCreateData } from '@opentrons/api-client' import type { LoadedLabware, LoadedModule, @@ -25,7 +25,7 @@ interface PythonLabwareOffsetSnippetProps { commands: RunTimeCommand[] labware: LoadedLabware[] modules: LoadedModule[] - labwareOffsets: LabwareOffsetCreateData[] | null + labwareOffsets: LegacyLabwareOffsetCreateData[] | null } export function PythonLabwareOffsetSnippet( diff --git a/app/src/organisms/Desktop/ChooseRobotToRunProtocolSlideout/useCreateRunFromProtocol.ts b/app/src/organisms/Desktop/ChooseRobotToRunProtocolSlideout/useCreateRunFromProtocol.ts index 58d1bdf08df..44ba2933189 100644 --- a/app/src/organisms/Desktop/ChooseRobotToRunProtocolSlideout/useCreateRunFromProtocol.ts +++ b/app/src/organisms/Desktop/ChooseRobotToRunProtocolSlideout/useCreateRunFromProtocol.ts @@ -12,7 +12,7 @@ import { getValidCustomLabwareFiles } from '/app/redux/custom-labware/selectors' import type { UseMutateFunction } from 'react-query' import type { HostConfig, - LabwareOffsetCreateData, + LegacyLabwareOffsetCreateData, Protocol, } from '@opentrons/api-client' import type { UseCreateRunMutationOptions } from '@opentrons/react-api-client/src/runs/useCreateRunMutation' @@ -35,7 +35,7 @@ export interface UseCreateRun { export function useCreateRunFromProtocol( options: UseCreateRunMutationOptions, hostOverride?: HostConfig | null, - labwareOffsets?: LabwareOffsetCreateData[] + labwareOffsets?: LegacyLabwareOffsetCreateData[] ): UseCreateRun { const contextHost = useHost() const host = diff --git a/app/src/organisms/LabwarePositionCheck/hooks/useLPCCommands/commands/modules.ts b/app/src/organisms/LabwarePositionCheck/hooks/useLPCCommands/commands/modules.ts index 6fd4f57c1d3..8c5487a66e9 100644 --- a/app/src/organisms/LabwarePositionCheck/hooks/useLPCCommands/commands/modules.ts +++ b/app/src/organisms/LabwarePositionCheck/hooks/useLPCCommands/commands/modules.ts @@ -10,7 +10,7 @@ import type { CompletedProtocolAnalysis, CreateCommand, } from '@opentrons/shared-data' -import type { LabwareOffsetLocation } from '@opentrons/api-client' +import type { LegacyLabwareOffsetLocation } from '@opentrons/api-client' export interface BuildModulePrepCommandsParams { step: CheckPositionsStep @@ -128,7 +128,7 @@ const thermocyclerInitCommands = ( const heaterShakerCleanupCommands = ( moduleId: string | undefined, - location: LabwareOffsetLocation + location: LegacyLabwareOffsetLocation ): CreateCommand[] => { const moduleType = (moduleId != null && diff --git a/app/src/organisms/LabwarePositionCheck/hooks/useLPCCommands/useApplyLPCOffsets.ts b/app/src/organisms/LabwarePositionCheck/hooks/useLPCCommands/useApplyLPCOffsets.ts index 64c505d9fbd..29183c98f06 100644 --- a/app/src/organisms/LabwarePositionCheck/hooks/useLPCCommands/useApplyLPCOffsets.ts +++ b/app/src/organisms/LabwarePositionCheck/hooks/useLPCCommands/useApplyLPCOffsets.ts @@ -2,7 +2,7 @@ import { useState } from 'react' import { useCreateLabwareOffsetMutation } from '@opentrons/react-api-client' -import type { LabwareOffsetCreateData } from '@opentrons/api-client' +import type { LegacyLabwareOffsetCreateData } from '@opentrons/api-client' import type { UseLPCCommandChildProps } from './types' export interface UseApplyLPCOffsetsProps extends UseLPCCommandChildProps { @@ -11,7 +11,7 @@ export interface UseApplyLPCOffsetsProps extends UseLPCCommandChildProps { export interface UseApplyLPCOffsetsResult { handleApplyOffsetsAndClose: ( - offsets: LabwareOffsetCreateData[] + offsets: LegacyLabwareOffsetCreateData[] ) => Promise isApplyingOffsets: boolean } @@ -26,7 +26,7 @@ export function useApplyLPCOffsets({ const { createLabwareOffset } = useCreateLabwareOffsetMutation() const handleApplyOffsetsAndClose = ( - offsets: LabwareOffsetCreateData[] + offsets: LegacyLabwareOffsetCreateData[] ): Promise => { setIsApplyingOffsets(true) return Promise.all( diff --git a/app/src/organisms/LabwarePositionCheck/hooks/useLPCCommands/useBuildOffsetsToApply.ts b/app/src/organisms/LabwarePositionCheck/hooks/useLPCCommands/useBuildOffsetsToApply.ts index 6b4b01d6632..56667853952 100644 --- a/app/src/organisms/LabwarePositionCheck/hooks/useLPCCommands/useBuildOffsetsToApply.ts +++ b/app/src/organisms/LabwarePositionCheck/hooks/useLPCCommands/useBuildOffsetsToApply.ts @@ -3,11 +3,11 @@ import { useStore } from 'react-redux' import { selectOffsetsToApply } from '/app/redux/protocol-runs' import type { State } from '/app/redux/types' -import type { LabwareOffsetCreateData } from '@opentrons/api-client' +import type { LegacyLabwareOffsetCreateData } from '@opentrons/api-client' import type { UseLPCCommandChildProps } from '/app/organisms/LabwarePositionCheck/hooks/useLPCCommands/types' export interface UseBuildOffsetsToApplyResult { - buildOffsetsToApply: () => LabwareOffsetCreateData[] + buildOffsetsToApply: () => LegacyLabwareOffsetCreateData[] } export interface UseApplyLPCOffsetsProps extends UseLPCCommandChildProps { diff --git a/app/src/organisms/LabwarePositionCheck/steps/ResultsSummary/OffsetTable.tsx b/app/src/organisms/LabwarePositionCheck/steps/ResultsSummary/OffsetTable.tsx index d35c3d2f885..46d8d430bbb 100644 --- a/app/src/organisms/LabwarePositionCheck/steps/ResultsSummary/OffsetTable.tsx +++ b/app/src/organisms/LabwarePositionCheck/steps/ResultsSummary/OffsetTable.tsx @@ -18,7 +18,7 @@ import { import { selectLwDisplayName } from '/app/redux/protocol-runs' import type { LabwareDefinition2 } from '@opentrons/shared-data' -import type { LabwareOffsetCreateData } from '@opentrons/api-client' +import type { LegacyLabwareOffsetCreateData } from '@opentrons/api-client' import type { LPCStepProps, ResultsSummaryStep, @@ -27,7 +27,7 @@ import type { LPCWizardState } from '/app/redux/protocol-runs' import type { State } from '/app/redux/types' interface OffsetTableProps extends LPCStepProps { - offsets: LabwareOffsetCreateData[] + offsets: LegacyLabwareOffsetCreateData[] labwareDefinitions: LabwareDefinition2[] } diff --git a/app/src/organisms/LabwarePositionCheck/steps/ResultsSummary/TableComponent.tsx b/app/src/organisms/LabwarePositionCheck/steps/ResultsSummary/TableComponent.tsx index 90ddb8edcf1..7e1dce4d58e 100644 --- a/app/src/organisms/LabwarePositionCheck/steps/ResultsSummary/TableComponent.tsx +++ b/app/src/organisms/LabwarePositionCheck/steps/ResultsSummary/TableComponent.tsx @@ -4,7 +4,7 @@ import { TerseOffsetTable } from '/app/organisms/TerseOffsetTable' import { OffsetTable } from './OffsetTable' import { getIsOnDevice } from '/app/redux/config' -import type { LabwareOffsetCreateData } from '@opentrons/api-client' +import type { LegacyLabwareOffsetCreateData } from '@opentrons/api-client' import type { LPCStepProps, ResultsSummaryStep, @@ -13,7 +13,7 @@ import type { State } from '/app/redux/types' import type { LPCWizardState } from '/app/redux/protocol-runs' interface TableComponentProps extends LPCStepProps { - offsetsToApply: LabwareOffsetCreateData[] + offsetsToApply: LegacyLabwareOffsetCreateData[] } export function TableComponent(props: TableComponentProps): JSX.Element { diff --git a/app/src/organisms/LabwarePositionCheck/types/steps.ts b/app/src/organisms/LabwarePositionCheck/types/steps.ts index 3cc781aebff..17caa519d1b 100644 --- a/app/src/organisms/LabwarePositionCheck/types/steps.ts +++ b/app/src/organisms/LabwarePositionCheck/types/steps.ts @@ -1,4 +1,4 @@ -import type { LabwareOffsetLocation } from '@opentrons/api-client' +import type { LegacyLabwareOffsetLocation } from '@opentrons/api-client' import type { NAV_STEPS } from '../constants' import type { LPCWizardContentProps } from './content' @@ -19,7 +19,7 @@ export type LPCStepProps = Omit< export interface PerformLPCStep { pipetteId: string labwareId: string - location: LabwareOffsetLocation + location: LegacyLabwareOffsetLocation definitionUri: string adapterId?: string moduleId?: string diff --git a/app/src/organisms/LegacyApplyHistoricOffsets/hooks/getLabwareLocationCombos.ts b/app/src/organisms/LegacyApplyHistoricOffsets/hooks/getLabwareLocationCombos.ts index 4dc49c5ca23..9422c3de1cf 100644 --- a/app/src/organisms/LegacyApplyHistoricOffsets/hooks/getLabwareLocationCombos.ts +++ b/app/src/organisms/LegacyApplyHistoricOffsets/hooks/getLabwareLocationCombos.ts @@ -9,10 +9,10 @@ import type { ProtocolAnalysisOutput, RunTimeCommand, } from '@opentrons/shared-data' -import type { LabwareOffsetLocation } from '@opentrons/api-client' +import type { LegacyLabwareOffsetLocation } from '@opentrons/api-client' export interface LabwareLocationCombo { - location: LabwareOffsetLocation + location: LegacyLabwareOffsetLocation definitionUri: string labwareId: string moduleId?: string @@ -167,7 +167,7 @@ function appendLocationComboIfUniq( function resolveModuleLocation( modules: ProtocolAnalysisOutput['modules'], moduleId: string -): LabwareOffsetLocation | null { +): LegacyLabwareOffsetLocation | null { const moduleEntity = modules.find(m => m.id === moduleId) if (moduleEntity == null) { console.warn( @@ -182,7 +182,7 @@ function resolveModuleLocation( } interface ResolveAdapterLocation { - adapterOffsetLocation: LabwareOffsetLocation | null + adapterOffsetLocation: LegacyLabwareOffsetLocation | null moduleIdUnderAdapter?: string } function resolveAdapterLocation( @@ -200,7 +200,7 @@ function resolveAdapterLocation( const labwareDefUri = labwareEntity.definitionUri let moduleIdUnderAdapter - let adapterOffsetLocation: LabwareOffsetLocation | null = null + let adapterOffsetLocation: LegacyLabwareOffsetLocation | null = null if ( labwareEntity.location === 'offDeck' || labwareEntity.location === 'systemLocation' @@ -211,7 +211,7 @@ function resolveAdapterLocation( return { adapterOffsetLocation: null } } else if ('moduleId' in labwareEntity.location) { const moduleId = labwareEntity.location.moduleId - const resolvedModuleLocation: LabwareOffsetLocation | null = resolveModuleLocation( + const resolvedModuleLocation: LegacyLabwareOffsetLocation | null = resolveModuleLocation( modules, moduleId ) diff --git a/app/src/organisms/LegacyLabwarePositionCheck/LabwarePositionCheckComponent.tsx b/app/src/organisms/LegacyLabwarePositionCheck/LabwarePositionCheckComponent.tsx index 6ff45018b1a..57309df764b 100644 --- a/app/src/organisms/LegacyLabwarePositionCheck/LabwarePositionCheckComponent.tsx +++ b/app/src/organisms/LegacyLabwarePositionCheck/LabwarePositionCheckComponent.tsx @@ -39,7 +39,7 @@ import type { RobotType, } from '@opentrons/shared-data' import type { - LabwareOffsetCreateData, + LegacyLabwareOffsetCreateData, LabwareOffset, CommandData, } from '@opentrons/api-client' @@ -310,7 +310,9 @@ export const LabwarePositionCheckComponent = ( robotType, } - const handleApplyOffsets = (offsets: LabwareOffsetCreateData[]): void => { + const handleApplyOffsets = ( + offsets: LegacyLabwareOffsetCreateData[] + ): void => { setIsApplyingOffsets(true) Promise.all(offsets.map(data => createLabwareOffset({ runId, data }))) .then(() => { diff --git a/app/src/organisms/LegacyLabwarePositionCheck/ResultsSummary.tsx b/app/src/organisms/LegacyLabwarePositionCheck/ResultsSummary.tsx index 22934c0f8a0..8e53f40c366 100644 --- a/app/src/organisms/LegacyLabwarePositionCheck/ResultsSummary.tsx +++ b/app/src/organisms/LegacyLabwarePositionCheck/ResultsSummary.tsx @@ -48,7 +48,7 @@ import type { } from '@opentrons/shared-data' import type { LabwareOffset, - LabwareOffsetCreateData, + LegacyLabwareOffsetCreateData, } from '@opentrons/api-client' import type { ResultsSummaryStep, WorkingOffset } from './types' import type { TFunction } from 'i18next' @@ -60,7 +60,7 @@ interface ResultsSummaryProps extends ResultsSummaryStep { protocolData: CompletedProtocolAnalysis workingOffsets: WorkingOffset[] existingOffsets: LabwareOffset[] - handleApplyOffsets: (offsets: LabwareOffsetCreateData[]) => void + handleApplyOffsets: (offsets: LegacyLabwareOffsetCreateData[]) => void isApplyingOffsets: boolean isDeletingMaintenanceRun?: boolean } @@ -86,7 +86,7 @@ export const ResultsSummary = ( const isOnDevice = useSelector(getIsOnDevice) const offsetsToApply = useMemo(() => { - return workingOffsets.map( + return workingOffsets.map( ({ initialPosition, finalPosition, labwareId, location }) => { const definitionUri = protocolData.labware.find(l => l.id === labwareId)?.definitionUri ?? @@ -269,7 +269,7 @@ const ScrollContainer = styled(Flex)` ` interface OffsetTableProps { - offsets: LabwareOffsetCreateData[] + offsets: LegacyLabwareOffsetCreateData[] labwareDefinitions: LabwareDefinition2[] } diff --git a/app/src/organisms/LegacyLabwarePositionCheck/types.ts b/app/src/organisms/LegacyLabwarePositionCheck/types.ts index 2ddd14c25d6..4cb26dbfaed 100644 --- a/app/src/organisms/LegacyLabwarePositionCheck/types.ts +++ b/app/src/organisms/LegacyLabwarePositionCheck/types.ts @@ -1,6 +1,9 @@ import type { SECTIONS } from './constants' import type { useCreateCommandMutation } from '@opentrons/react-api-client' -import type { LabwareOffsetLocation, VectorOffset } from '@opentrons/api-client' +import type { + LegacyLabwareOffsetLocation, + VectorOffset, +} from '@opentrons/api-client' import type { LabwareDefinition2 } from '@opentrons/shared-data' export type LabwarePositionCheckStep = @@ -20,7 +23,7 @@ export interface CheckTipRacksStep { section: typeof SECTIONS.CHECK_TIP_RACKS pipetteId: string labwareId: string - location: LabwareOffsetLocation + location: LegacyLabwareOffsetLocation definitionUri: string adapterId?: string } @@ -32,7 +35,7 @@ export interface PickUpTipStep { section: typeof SECTIONS.PICK_UP_TIP pipetteId: string labwareId: string - location: LabwareOffsetLocation + location: LegacyLabwareOffsetLocation definitionUri: string adapterId?: string } @@ -40,7 +43,7 @@ export interface CheckPositionsStep { section: typeof SECTIONS.CHECK_POSITIONS pipetteId: string labwareId: string - location: LabwareOffsetLocation + location: LegacyLabwareOffsetLocation definitionUri: string moduleId?: string } @@ -48,7 +51,7 @@ export interface CheckLabwareStep { section: typeof SECTIONS.CHECK_LABWARE pipetteId: string labwareId: string - location: LabwareOffsetLocation + location: LegacyLabwareOffsetLocation definitionUri: string moduleId?: string adapterId?: string @@ -57,7 +60,7 @@ export interface ReturnTipStep { section: typeof SECTIONS.RETURN_TIP pipetteId: string labwareId: string - location: LabwareOffsetLocation + location: LegacyLabwareOffsetLocation definitionUri: string adapterId?: string } @@ -80,13 +83,13 @@ export type CreateRunCommand = ( interface InitialPositionAction { type: 'initialPosition' labwareId: string - location: LabwareOffsetLocation + location: LegacyLabwareOffsetLocation position: VectorOffset | null } interface FinalPositionAction { type: 'finalPosition' labwareId: string - location: LabwareOffsetLocation + location: LegacyLabwareOffsetLocation position: VectorOffset | null } interface TipPickUpOffsetAction { @@ -99,7 +102,7 @@ export type RegisterPositionAction = | TipPickUpOffsetAction export interface WorkingOffset { labwareId: string - location: LabwareOffsetLocation + location: LegacyLabwareOffsetLocation initialPosition: VectorOffset | null finalPosition: VectorOffset | null } diff --git a/app/src/organisms/LegacyLabwarePositionCheck/utils/getDisplayLocation.ts b/app/src/organisms/LegacyLabwarePositionCheck/utils/getDisplayLocation.ts index d70b741c48d..88ab9976719 100644 --- a/app/src/organisms/LegacyLabwarePositionCheck/utils/getDisplayLocation.ts +++ b/app/src/organisms/LegacyLabwarePositionCheck/utils/getDisplayLocation.ts @@ -6,10 +6,10 @@ import { } from '@opentrons/shared-data' import type { i18n, TFunction } from 'i18next' import type { LabwareDefinition2 } from '@opentrons/shared-data' -import type { LabwareOffsetLocation } from '@opentrons/api-client' +import type { LegacyLabwareOffsetLocation } from '@opentrons/api-client' export function getDisplayLocation( - location: LabwareOffsetLocation, + location: LegacyLabwareOffsetLocation, labwareDefinitions: LabwareDefinition2[], t: TFunction, i18n: i18n, diff --git a/app/src/organisms/ODD/ProtocolSetup/ProtocolSetupParameters/ProtocolSetupParameters.tsx b/app/src/organisms/ODD/ProtocolSetup/ProtocolSetupParameters/ProtocolSetupParameters.tsx index ec4df679049..519a5a32150 100644 --- a/app/src/organisms/ODD/ProtocolSetup/ProtocolSetupParameters/ProtocolSetupParameters.tsx +++ b/app/src/organisms/ODD/ProtocolSetup/ProtocolSetupParameters/ProtocolSetupParameters.tsx @@ -40,12 +40,15 @@ import type { CsvFileParameterFileData, } from '@opentrons/shared-data' import type { ProtocolSetupStepStatus } from '../ProtocolSetupStep' -import type { FileData, LabwareOffsetCreateData } from '@opentrons/api-client' +import type { + FileData, + LegacyLabwareOffsetCreateData, +} from '@opentrons/api-client' interface ProtocolSetupParametersProps { protocolId: string runTimeParameters: RunTimeParameter[] - labwareOffsets?: LabwareOffsetCreateData[] + labwareOffsets?: LegacyLabwareOffsetCreateData[] mostRecentAnalysis?: CompletedProtocolAnalysis | null } diff --git a/app/src/organisms/TerseOffsetTable/index.tsx b/app/src/organisms/TerseOffsetTable/index.tsx index 5fdbaf162a2..d1f4ac13da5 100644 --- a/app/src/organisms/TerseOffsetTable/index.tsx +++ b/app/src/organisms/TerseOffsetTable/index.tsx @@ -21,11 +21,11 @@ import { DIRECTION_ROW, } from '@opentrons/components' -import type { LabwareOffsetCreateData } from '@opentrons/api-client' +import type { LegacyLabwareOffsetCreateData } from '@opentrons/api-client' import type { LabwareDefinition2 } from '@opentrons/shared-data' export interface TerseOffsetTableProps { - offsets: LabwareOffsetCreateData[] + offsets: LegacyLabwareOffsetCreateData[] labwareDefinitions: LabwareDefinition2[] } diff --git a/app/src/redux/protocol-runs/selectors/lpc/labware.ts b/app/src/redux/protocol-runs/selectors/lpc/labware.ts index afce4ae46e1..fd831163cc2 100644 --- a/app/src/redux/protocol-runs/selectors/lpc/labware.ts +++ b/app/src/redux/protocol-runs/selectors/lpc/labware.ts @@ -14,7 +14,10 @@ import { getCurrentOffsetForLabwareInLocation } from '/app/transformations/analy import { getItemLabwareDef } from './transforms' import type { Selector } from 'reselect' -import type { VectorOffset, LabwareOffsetLocation } from '@opentrons/api-client' +import type { + VectorOffset, + LegacyLabwareOffsetLocation, +} from '@opentrons/api-client' import type { LabwareDefinition2, Coordinates } from '@opentrons/shared-data' import type { State } from '../../../types' @@ -88,7 +91,7 @@ export const selectActiveLwExistingOffset = ( export interface SelectOffsetsToApplyResult { definitionUri: string - location: LabwareOffsetLocation + location: LegacyLabwareOffsetLocation vector: Coordinates } diff --git a/app/src/redux/protocol-runs/types/lpc.ts b/app/src/redux/protocol-runs/types/lpc.ts index aec42e6eb98..0e31a166bf1 100644 --- a/app/src/redux/protocol-runs/types/lpc.ts +++ b/app/src/redux/protocol-runs/types/lpc.ts @@ -4,7 +4,7 @@ import type { CompletedProtocolAnalysis, } from '@opentrons/shared-data' import type { - LabwareOffsetLocation, + LegacyLabwareOffsetLocation, VectorOffset, LabwareOffset, } from '@opentrons/api-client' @@ -15,13 +15,13 @@ import type { StepsInfo } from '/app/organisms/LabwarePositionCheck/redux/types' export interface PositionParams { labwareId: string - location: LabwareOffsetLocation + location: LegacyLabwareOffsetLocation position: VectorOffset | null } export interface WorkingOffset { labwareId: string - location: LabwareOffsetLocation + location: LegacyLabwareOffsetLocation initialPosition: VectorOffset | null finalPosition: VectorOffset | null } diff --git a/app/src/transformations/analysis/getLabwareOffsetLocation.ts b/app/src/transformations/analysis/getLabwareOffsetLocation.ts index 526c3f780cb..6043c4c7eca 100644 --- a/app/src/transformations/analysis/getLabwareOffsetLocation.ts +++ b/app/src/transformations/analysis/getLabwareOffsetLocation.ts @@ -2,7 +2,7 @@ import { getModuleInitialLoadInfo, getLabwareLocation, } from '/app/transformations/commands' -import type { LabwareOffsetLocation } from '@opentrons/api-client' +import type { LegacyLabwareOffsetLocation } from '@opentrons/api-client' import type { LoadedModule, LoadedLabware, @@ -17,7 +17,7 @@ export const getLabwareOffsetLocation = ( commands: ProtocolAnalysisOutput['commands'], modules: LoadedModule[], labware: LoadedLabware[] -): LabwareOffsetLocation | null => { +): LegacyLabwareOffsetLocation | null => { const labwareLocation = getLabwareLocation(labwareId, commands) if (labwareLocation === 'offDeck' || labwareLocation === 'systemLocation') { diff --git a/react-api-client/src/runs/__tests__/useCreateLabwareOffsetsMutation.test.tsx b/react-api-client/src/runs/__tests__/useCreateLabwareOffsetsMutation.test.tsx index beb57a9ca72..e2b83c5741c 100644 --- a/react-api-client/src/runs/__tests__/useCreateLabwareOffsetsMutation.test.tsx +++ b/react-api-client/src/runs/__tests__/useCreateLabwareOffsetsMutation.test.tsx @@ -6,7 +6,10 @@ import { createLabwareOffset } from '@opentrons/api-client' import { useHost } from '../../api' import { useCreateLabwareOffsetMutation } from '../useCreateLabwareOffsetMutation' -import type { HostConfig, LabwareOffsetCreateData } from '@opentrons/api-client' +import type { + HostConfig, + LegacyLabwareOffsetCreateData, +} from '@opentrons/api-client' vi.mock('@opentrons/api-client') vi.mock('../../api/useHost') @@ -19,7 +22,7 @@ const OFFSET = { x: 1, y: 2, z: 3 } describe('useCreateLabwareOffsetMutation hook', () => { let wrapper: React.FunctionComponent<{ children: React.ReactNode }> - let labwareOffset: LabwareOffsetCreateData + let labwareOffset: LegacyLabwareOffsetCreateData beforeEach(() => { const queryClient = new QueryClient() diff --git a/react-api-client/src/runs/useCreateLabwareOffsetMutation.ts b/react-api-client/src/runs/useCreateLabwareOffsetMutation.ts index adf92f9657c..f1b04505b30 100644 --- a/react-api-client/src/runs/useCreateLabwareOffsetMutation.ts +++ b/react-api-client/src/runs/useCreateLabwareOffsetMutation.ts @@ -4,13 +4,13 @@ import { useHost } from '../api' import type { HostConfig, Run, - LabwareOffsetCreateData, + LegacyLabwareOffsetCreateData, } from '@opentrons/api-client' import type { UseMutationResult, UseMutateAsyncFunction } from 'react-query' interface CreateLabwareOffsetParams { runId: string - data: LabwareOffsetCreateData + data: LegacyLabwareOffsetCreateData } export type UseCreateLabwareOffsetMutationResult = UseMutationResult< diff --git a/robot-server/robot_server/labware_offsets/router.py b/robot-server/robot_server/labware_offsets/router.py index 3a01ca73278..e75bb27d926 100644 --- a/robot-server/robot_server/labware_offsets/router.py +++ b/robot-server/robot_server/labware_offsets/router.py @@ -1,6 +1,5 @@ """FastAPI endpoint functions for the `/labwareOffsets` endpoints.""" - from datetime import datetime import textwrap from typing import Annotated, Literal @@ -10,7 +9,11 @@ from pydantic.json_schema import SkipJsonSchema from server_utils.fastapi_utils.light_router import LightRouter -from opentrons.protocol_engine import LabwareOffset, LabwareOffsetCreate, ModuleModel +from opentrons.protocol_engine import ( + LabwareOffset, + LegacyLabwareOffsetCreate, + ModuleModel, +) from opentrons.types import DeckSlotName from robot_server.labware_offsets.models import LabwareOffsetNotFound @@ -54,7 +57,7 @@ async def post_labware_offset( # noqa: D103 store: Annotated[LabwareOffsetStore, fastapi.Depends(get_labware_offset_store)], new_offset_id: Annotated[str, fastapi.Depends(get_unique_id)], new_offset_created_at: Annotated[datetime, fastapi.Depends(get_current_time)], - request_body: Annotated[RequestModel[LabwareOffsetCreate], fastapi.Body()], + request_body: Annotated[RequestModel[LegacyLabwareOffsetCreate], fastapi.Body()], ) -> PydanticResponse[SimpleBody[LabwareOffset]]: new_offset = LabwareOffset.model_construct( id=new_offset_id, diff --git a/robot-server/robot_server/labware_offsets/store.py b/robot-server/robot_server/labware_offsets/store.py index a605f75da3e..dbeccc728a1 100644 --- a/robot-server/robot_server/labware_offsets/store.py +++ b/robot-server/robot_server/labware_offsets/store.py @@ -5,7 +5,7 @@ from opentrons.protocol_engine.types import ( LabwareOffset, - LabwareOffsetLocation, + LegacyLabwareOffsetLocation, LabwareOffsetVector, ModuleModel, ) @@ -154,7 +154,7 @@ def _sql_to_pydantic(row: sqlalchemy.engine.Row) -> LabwareOffset: id=row.offset_id, createdAt=row.created_at, definitionUri=row.definition_uri, - location=LabwareOffsetLocation( + location=LegacyLabwareOffsetLocation( slotName=DeckSlotName(row.location_slot_name), moduleModel=row.location_module_model, definitionUri=row.location_definition_uri, diff --git a/robot-server/robot_server/maintenance_runs/maintenance_run_data_manager.py b/robot-server/robot_server/maintenance_runs/maintenance_run_data_manager.py index dfc76945f81..2a27e0c9a67 100644 --- a/robot-server/robot_server/maintenance_runs/maintenance_run_data_manager.py +++ b/robot-server/robot_server/maintenance_runs/maintenance_run_data_manager.py @@ -1,9 +1,11 @@ """Manage current maintenance run data.""" + from datetime import datetime -from typing import List, Optional, Callable +from typing import Optional, Callable, Sequence from opentrons.protocol_engine import ( EngineStatus, + LegacyLabwareOffsetCreate, LabwareOffsetCreate, StateSummary, CommandSlice, @@ -87,7 +89,7 @@ async def create( self, run_id: str, created_at: datetime, - labware_offsets: List[LabwareOffsetCreate], + labware_offsets: Sequence[LabwareOffsetCreate | LegacyLabwareOffsetCreate], deck_configuration: DeckConfigurationType, notify_publishers: Callable[[], None], ) -> MaintenanceRun: diff --git a/robot-server/robot_server/maintenance_runs/maintenance_run_models.py b/robot-server/robot_server/maintenance_runs/maintenance_run_models.py index 8bde7ea7aff..25b3b40ae74 100644 --- a/robot-server/robot_server/maintenance_runs/maintenance_run_models.py +++ b/robot-server/robot_server/maintenance_runs/maintenance_run_models.py @@ -1,4 +1,5 @@ """Request and response models for maintenance run resources.""" + from datetime import datetime from pydantic import BaseModel, Field from typing import List, Optional @@ -11,6 +12,7 @@ LoadedModule, LabwareOffset, LabwareOffsetCreate, + LegacyLabwareOffsetCreate, Liquid, LiquidClassRecordWithId, ) @@ -89,7 +91,7 @@ class MaintenanceRun(ResourceModel): class MaintenanceRunCreate(BaseModel): """Create request data for a new maintenance run.""" - labwareOffsets: List[LabwareOffsetCreate] = Field( + labwareOffsets: List[LegacyLabwareOffsetCreate | LabwareOffsetCreate] = Field( default_factory=list, description="Labware offsets to apply as labware are loaded.", ) diff --git a/robot-server/robot_server/maintenance_runs/maintenance_run_orchestrator_store.py b/robot-server/robot_server/maintenance_runs/maintenance_run_orchestrator_store.py index 530cdc87563..31ab9228d74 100644 --- a/robot-server/robot_server/maintenance_runs/maintenance_run_orchestrator_store.py +++ b/robot-server/robot_server/maintenance_runs/maintenance_run_orchestrator_store.py @@ -1,14 +1,16 @@ """In-memory storage of ProtocolEngine instances.""" + import asyncio import logging from datetime import datetime -from typing import List, Optional, Callable +from typing import Optional, Callable, Sequence from opentrons.protocol_engine.errors.exceptions import EStopActivatedError from opentrons.protocol_engine.types import PostRunHardwareState, DeckConfigurationType from opentrons.protocol_engine import ( DeckType, LabwareOffsetCreate, + LegacyLabwareOffsetCreate, StateSummary, CommandSlice, CommandPointer, @@ -146,7 +148,7 @@ async def create( self, run_id: str, created_at: datetime, - labware_offsets: List[LabwareOffsetCreate], + labware_offsets: Sequence[LegacyLabwareOffsetCreate | LabwareOffsetCreate], notify_publishers: Callable[[], None], deck_configuration: Optional[DeckConfigurationType] = [], ) -> StateSummary: @@ -265,7 +267,9 @@ async def add_command_and_wait_for_interval( command=request, wait_until_complete=wait_until_complete, timeout=timeout ) - def add_labware_offset(self, request: LabwareOffsetCreate) -> LabwareOffset: + def add_labware_offset( + self, request: LegacyLabwareOffsetCreate | LabwareOffsetCreate + ) -> LabwareOffset: """Add a new labware offset to state.""" return self.run_orchestrator.add_labware_offset(request) diff --git a/robot-server/robot_server/maintenance_runs/router/labware_router.py b/robot-server/robot_server/maintenance_runs/router/labware_router.py index 53dce4ae6eb..c64e8b7db97 100644 --- a/robot-server/robot_server/maintenance_runs/router/labware_router.py +++ b/robot-server/robot_server/maintenance_runs/router/labware_router.py @@ -1,4 +1,5 @@ """Router for /maintenance_runs endpoints dealing with labware offsets and definitions.""" + from typing import Annotated import logging @@ -7,7 +8,11 @@ from opentrons_shared_data.labware.labware_definition import LabwareDefinition from server_utils.fastapi_utils.light_router import LightRouter -from opentrons.protocol_engine import LabwareOffsetCreate, LabwareOffset +from opentrons.protocol_engine import ( + LabwareOffsetCreate, + LegacyLabwareOffsetCreate, + LabwareOffset, +) from robot_server.errors.error_responses import ErrorBody from robot_server.service.json_api import RequestModel, SimpleBody, PydanticResponse @@ -40,7 +45,7 @@ }, ) async def add_labware_offset( - request_body: RequestModel[LabwareOffsetCreate], + request_body: RequestModel[LabwareOffsetCreate | LegacyLabwareOffsetCreate], run_orchestrator_store: Annotated[ MaintenanceRunOrchestratorStore, Depends(get_maintenance_run_orchestrator_store) ], diff --git a/robot-server/robot_server/runs/router/labware_router.py b/robot-server/robot_server/runs/router/labware_router.py index f9264da51e6..78c880a2df5 100644 --- a/robot-server/robot_server/runs/router/labware_router.py +++ b/robot-server/robot_server/runs/router/labware_router.py @@ -9,7 +9,11 @@ from server_utils.fastapi_utils.light_router import LightRouter -from opentrons.protocol_engine import LabwareOffsetCreate, LabwareOffset +from opentrons.protocol_engine import ( + LabwareOffsetCreate, + LegacyLabwareOffsetCreate, + LabwareOffset, +) from robot_server.errors.error_responses import ErrorBody from robot_server.service.json_api import ( @@ -47,7 +51,7 @@ }, ) async def add_labware_offset( - request_body: RequestModel[LabwareOffsetCreate], + request_body: RequestModel[LegacyLabwareOffsetCreate | LabwareOffsetCreate], run_orchestrator_store: Annotated[ RunOrchestratorStore, Depends(get_run_orchestrator_store) ], diff --git a/robot-server/robot_server/runs/run_data_manager.py b/robot-server/robot_server/runs/run_data_manager.py index fa937f7cb68..86473667987 100644 --- a/robot-server/robot_server/runs/run_data_manager.py +++ b/robot-server/robot_server/runs/run_data_manager.py @@ -1,7 +1,7 @@ """Manage current and historical run data.""" from datetime import datetime -from typing import Dict, List, Optional, Callable, Union, Mapping +from typing import Dict, List, Optional, Callable, Union, Mapping, Sequence from opentrons_shared_data.labware.labware_definition import LabwareDefinition from opentrons_shared_data.errors.exceptions import InvalidStoredData, EnumeratedError @@ -10,6 +10,7 @@ from opentrons.protocol_engine import ( EngineStatus, LabwareOffsetCreate, + LegacyLabwareOffsetCreate, StateSummary, CommandSlice, CommandErrorSlice, @@ -181,7 +182,7 @@ async def create( self, run_id: str, created_at: datetime, - labware_offsets: List[LabwareOffsetCreate], + labware_offsets: Sequence[LabwareOffsetCreate | LegacyLabwareOffsetCreate], deck_configuration: DeckConfigurationType, file_provider: FileProvider, run_time_param_values: Optional[PrimitiveRunTimeParamValuesType], diff --git a/robot-server/robot_server/runs/run_models.py b/robot-server/robot_server/runs/run_models.py index 4d5da7560c0..f530707d4c3 100644 --- a/robot-server/robot_server/runs/run_models.py +++ b/robot-server/robot_server/runs/run_models.py @@ -1,4 +1,5 @@ """Request and response models for run resources.""" + from datetime import datetime from enum import Enum @@ -16,6 +17,7 @@ LoadedLabware, LoadedModule, LabwareOffset, + LegacyLabwareOffsetCreate, LabwareOffsetCreate, Liquid, LiquidClassRecordWithId, @@ -265,7 +267,7 @@ class RunCreate(BaseModel): None, description="Protocol resource ID that this run will be using, if applicable.", ) - labwareOffsets: List[LabwareOffsetCreate] = Field( + labwareOffsets: List[LegacyLabwareOffsetCreate | LabwareOffsetCreate] = Field( default_factory=list, description="Labware offsets to apply as labware are loaded.", ) diff --git a/robot-server/robot_server/runs/run_orchestrator_store.py b/robot-server/robot_server/runs/run_orchestrator_store.py index adb7cac151e..38a6c2e23c6 100644 --- a/robot-server/robot_server/runs/run_orchestrator_store.py +++ b/robot-server/robot_server/runs/run_orchestrator_store.py @@ -2,7 +2,7 @@ import asyncio import logging -from typing import Dict, List, Optional, Callable, Mapping +from typing import Dict, List, Optional, Callable, Mapping, Sequence from opentrons.types import NozzleMapInterface from opentrons.protocol_engine.errors.exceptions import EStopActivatedError @@ -33,6 +33,7 @@ from opentrons.protocol_engine import ( DeckType, LabwareOffsetCreate, + LegacyLabwareOffsetCreate, StateSummary, CommandSlice, CommandErrorSlice, @@ -192,7 +193,7 @@ async def get_default_orchestrator(self) -> RunOrchestrator: async def create( self, run_id: str, - labware_offsets: List[LabwareOffsetCreate], + labware_offsets: Sequence[LabwareOffsetCreate | LegacyLabwareOffsetCreate], initial_error_recovery_policy: error_recovery_policy.ErrorRecoveryPolicy, deck_configuration: DeckConfigurationType, file_provider: FileProvider, @@ -408,7 +409,9 @@ def run_was_started(self) -> bool: """Get whether the run has started.""" return self.run_orchestrator.run_has_started() - def add_labware_offset(self, request: LabwareOffsetCreate) -> LabwareOffset: + def add_labware_offset( + self, request: LabwareOffsetCreate | LegacyLabwareOffsetCreate + ) -> LabwareOffset: """Add a new labware offset to state.""" return self.run_orchestrator.add_labware_offset(request) diff --git a/robot-server/tests/integration/http_api/runs/test_protocol_run.tavern.yaml b/robot-server/tests/integration/http_api/runs/test_protocol_run.tavern.yaml index 732726d39e9..038f510d1dc 100644 --- a/robot-server/tests/integration/http_api/runs/test_protocol_run.tavern.yaml +++ b/robot-server/tests/integration/http_api/runs/test_protocol_run.tavern.yaml @@ -105,6 +105,9 @@ stages: definitionUri: opentrons/biorad_96_wellplate_200ul_pcr/1 location: slotName: '1' + locationSequence: + - kind: 'onAddressableArea' + addressableAreaName: '1' vector: x: 1.11 y: 2.22 @@ -264,6 +267,9 @@ stages: definitionUri: opentrons/biorad_96_wellplate_200ul_pcr/1 location: slotName: '1' + locationSequence: + - kind: 'onAddressableArea' + addressableAreaName: '1' vector: x: 1.11 y: 2.22 diff --git a/robot-server/tests/labware_offsets/test_store.py b/robot-server/tests/labware_offsets/test_store.py index a23b55aff9e..0b6048da86b 100644 --- a/robot-server/tests/labware_offsets/test_store.py +++ b/robot-server/tests/labware_offsets/test_store.py @@ -7,7 +7,7 @@ from opentrons.protocol_engine import ( LabwareOffset, - LabwareOffsetLocation, + LegacyLabwareOffsetLocation, LabwareOffsetVector, ) from opentrons.protocol_engine.types import ModuleModel @@ -35,7 +35,7 @@ def test_filter_fields(subject: LabwareOffsetStore) -> None: id="a", createdAt=datetime.now(timezone.utc), definitionUri="definitionUri a", - location=LabwareOffsetLocation( + location=LegacyLabwareOffsetLocation( slotName=DeckSlotName.SLOT_A1, moduleModel=ModuleModel.THERMOCYCLER_MODULE_V1, definitionUri="location.definitionUri a", @@ -46,7 +46,7 @@ def test_filter_fields(subject: LabwareOffsetStore) -> None: id="b", createdAt=datetime.now(timezone.utc), definitionUri="definitionUri b", - location=LabwareOffsetLocation( + location=LegacyLabwareOffsetLocation( slotName=DeckSlotName.SLOT_B1, moduleModel=ModuleModel.MAGNETIC_BLOCK_V1, definitionUri="location.definitionUri b", @@ -100,7 +100,7 @@ def test_filter_combinations(subject: LabwareOffsetStore) -> None: id=id, createdAt=datetime.now(timezone.utc), definitionUri=definition_uri, - location=LabwareOffsetLocation(slotName=DeckSlotName.SLOT_A1), + location=LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_A1), vector=LabwareOffsetVector(x=1, y=2, z=3), ) for (id, definition_uri) in ids_and_definition_uris @@ -141,7 +141,7 @@ def test_delete(subject: LabwareOffsetStore) -> None: id=id, createdAt=datetime.now(timezone.utc), definitionUri="", - location=LabwareOffsetLocation(slotName=DeckSlotName.SLOT_A1), + location=LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_A1), vector=LabwareOffsetVector(x=1, y=2, z=3), ) for id in ["id-a", "id-b", "id-c"] diff --git a/robot-server/tests/maintenance_runs/router/test_base_router.py b/robot-server/tests/maintenance_runs/router/test_base_router.py index 29a9c81a3b7..b7b1182fa91 100644 --- a/robot-server/tests/maintenance_runs/router/test_base_router.py +++ b/robot-server/tests/maintenance_runs/router/test_base_router.py @@ -1,10 +1,11 @@ """Tests for base /runs routes.""" + import pytest from datetime import datetime from decoy import Decoy from opentrons.types import DeckSlotName -from opentrons.protocol_engine import LabwareOffsetCreate, types as pe_types +from opentrons.protocol_engine import types as pe_types from robot_server.errors.error_responses import ApiError from robot_server.service.json_api import ( @@ -44,11 +45,11 @@ def mock_notify_publishers() -> None: @pytest.fixture -def labware_offset_create() -> LabwareOffsetCreate: +def labware_offset_create() -> pe_types.LegacyLabwareOffsetCreate: """Get a labware offset create request value object.""" - return pe_types.LabwareOffsetCreate( + return pe_types.LegacyLabwareOffsetCreate( definitionUri="namespace_1/load_name_1/123", - location=pe_types.LabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + location=pe_types.LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), vector=pe_types.LabwareOffsetVector(x=1, y=2, z=3), ) diff --git a/robot-server/tests/maintenance_runs/router/test_labware_router.py b/robot-server/tests/maintenance_runs/router/test_labware_router.py index 2b03b13c9e8..72b1e95e2f7 100644 --- a/robot-server/tests/maintenance_runs/router/test_labware_router.py +++ b/robot-server/tests/maintenance_runs/router/test_labware_router.py @@ -1,4 +1,5 @@ """Tests for /runs routes dealing with labware offsets and definitions.""" + import pytest from datetime import datetime from decoy import Decoy @@ -55,9 +56,9 @@ async def test_add_labware_offset( run: MaintenanceRun, ) -> None: """It should add the labware offset to the engine, assuming the run is current.""" - labware_offset_request = pe_types.LabwareOffsetCreate( + labware_offset_request = pe_types.LegacyLabwareOffsetCreate( definitionUri="namespace_1/load_name_1/123", - location=pe_types.LabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + location=pe_types.LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), vector=pe_types.LabwareOffsetVector(x=1, y=2, z=3), ) @@ -65,7 +66,7 @@ async def test_add_labware_offset( id="labware-offset-id", createdAt=datetime(year=2022, month=2, day=2), definitionUri="labware-definition-uri", - location=pe_types.LabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + location=pe_types.LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), vector=pe_types.LabwareOffsetVector(x=0, y=0, z=0), ) diff --git a/robot-server/tests/maintenance_runs/test_engine_store.py b/robot-server/tests/maintenance_runs/test_engine_store.py index ed9987f5e77..019bb4a913d 100644 --- a/robot-server/tests/maintenance_runs/test_engine_store.py +++ b/robot-server/tests/maintenance_runs/test_engine_store.py @@ -1,4 +1,5 @@ """Tests for the MaintenanceRunOrchestratorStore interface.""" + from datetime import datetime import pytest @@ -95,9 +96,9 @@ async def test_create_engine_with_labware_offsets( subject: MaintenanceRunOrchestratorStore, ) -> None: """It should create an engine for a run with labware offsets.""" - labware_offset = pe_types.LabwareOffsetCreate( + labware_offset = pe_types.LegacyLabwareOffsetCreate( definitionUri="namespace/load_name/version", - location=pe_types.LabwareOffsetLocation(slotName=DeckSlotName.SLOT_5), + location=pe_types.LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_5), vector=pe_types.LabwareOffsetVector(x=1, y=2, z=3), ) @@ -113,7 +114,12 @@ async def test_create_engine_with_labware_offsets( id=matchers.IsA(str), createdAt=matchers.IsA(datetime), definitionUri="namespace/load_name/version", - location=pe_types.LabwareOffsetLocation(slotName=DeckSlotName.SLOT_5), + location=pe_types.LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_5), + locationSequence=[ + pe_types.OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="5" + ) + ], vector=pe_types.LabwareOffsetVector(x=1, y=2, z=3), ) ] diff --git a/robot-server/tests/maintenance_runs/test_run_data_manager.py b/robot-server/tests/maintenance_runs/test_run_data_manager.py index 634eaab6ce5..768bdbe1029 100644 --- a/robot-server/tests/maintenance_runs/test_run_data_manager.py +++ b/robot-server/tests/maintenance_runs/test_run_data_manager.py @@ -160,9 +160,9 @@ async def test_create_with_options( run_id = "hello world" created_at = datetime(year=2021, month=1, day=1) - labware_offset = pe_types.LabwareOffsetCreate( + labware_offset = pe_types.LegacyLabwareOffsetCreate( definitionUri="namespace/load_name/version", - location=pe_types.LabwareOffsetLocation(slotName=DeckSlotName.SLOT_5), + location=pe_types.LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_5), vector=pe_types.LabwareOffsetVector(x=1, y=2, z=3), ) diff --git a/robot-server/tests/runs/router/test_base_router.py b/robot-server/tests/runs/router/test_base_router.py index 0350bb4d0b0..bf475b5a0c0 100644 --- a/robot-server/tests/runs/router/test_base_router.py +++ b/robot-server/tests/runs/router/test_base_router.py @@ -9,7 +9,6 @@ from opentrons.types import DeckSlotName, Point, NozzleConfigurationType from opentrons.protocol_engine import ( - LabwareOffsetCreate, types as pe_types, errors as pe_errors, CommandErrorSlice, @@ -101,11 +100,11 @@ def mock_data_files_directory(decoy: Decoy) -> Path: @pytest.fixture -def labware_offset_create() -> LabwareOffsetCreate: +def labware_offset_create() -> pe_types.LegacyLabwareOffsetCreate: """Get a labware offset create request value object.""" - return pe_types.LabwareOffsetCreate( + return pe_types.LegacyLabwareOffsetCreate( definitionUri="namespace_1/load_name_1/123", - location=pe_types.LabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + location=pe_types.LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), vector=pe_types.LabwareOffsetVector(x=1, y=2, z=3), ) @@ -114,7 +113,7 @@ async def test_create_run( decoy: Decoy, mock_run_data_manager: RunDataManager, mock_run_auto_deleter: RunAutoDeleter, - labware_offset_create: pe_types.LabwareOffsetCreate, + labware_offset_create: pe_types.LegacyLabwareOffsetCreate, mock_deck_configuration_store: DeckConfigurationStore, mock_file_provider_wrapper: FileProviderWrapper, mock_protocol_store: ProtocolStore, diff --git a/robot-server/tests/runs/router/test_labware_router.py b/robot-server/tests/runs/router/test_labware_router.py index bf55021a6ad..2b55b4097f6 100644 --- a/robot-server/tests/runs/router/test_labware_router.py +++ b/robot-server/tests/runs/router/test_labware_router.py @@ -59,9 +59,9 @@ async def test_add_labware_offset( run: Run, ) -> None: """It should add the labware offset to the engine, assuming the run is current.""" - labware_offset_request = pe_types.LabwareOffsetCreate( + labware_offset_request = pe_types.LegacyLabwareOffsetCreate( definitionUri="namespace_1/load_name_1/123", - location=pe_types.LabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + location=pe_types.LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), vector=pe_types.LabwareOffsetVector(x=1, y=2, z=3), ) @@ -69,7 +69,7 @@ async def test_add_labware_offset( id="labware-offset-id", createdAt=datetime(year=2022, month=2, day=2), definitionUri="labware-definition-uri", - location=pe_types.LabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + location=pe_types.LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), vector=pe_types.LabwareOffsetVector(x=0, y=0, z=0), ) @@ -95,9 +95,9 @@ async def test_add_labware_offset_not_current( """It should 409 if the run is not current.""" not_current_run = run.model_copy(update={"current": False}) - labware_offset_request = pe_types.LabwareOffsetCreate( + labware_offset_request = pe_types.LegacyLabwareOffsetCreate( definitionUri="namespace_1/load_name_1/123", - location=pe_types.LabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + location=pe_types.LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), vector=pe_types.LabwareOffsetVector(x=1, y=2, z=3), ) diff --git a/robot-server/tests/runs/test_run_orchestrator_store.py b/robot-server/tests/runs/test_run_orchestrator_store.py index b0f8354e494..a8564cece99 100644 --- a/robot-server/tests/runs/test_run_orchestrator_store.py +++ b/robot-server/tests/runs/test_run_orchestrator_store.py @@ -1,4 +1,5 @@ """Tests for the EngineStore interface.""" + from datetime import datetime import pytest from decoy import Decoy, matchers @@ -103,9 +104,9 @@ async def test_create_engine_with_labware_offsets( subject: RunOrchestratorStore, ) -> None: """It should create an engine for a run with labware offsets.""" - labware_offset = pe_types.LabwareOffsetCreate( + labware_offset = pe_types.LegacyLabwareOffsetCreate( definitionUri="namespace/load_name/version", - location=pe_types.LabwareOffsetLocation(slotName=DeckSlotName.SLOT_5), + location=pe_types.LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_5), vector=pe_types.LabwareOffsetVector(x=1, y=2, z=3), ) @@ -124,7 +125,12 @@ async def test_create_engine_with_labware_offsets( id=matchers.IsA(str), createdAt=matchers.IsA(datetime), definitionUri="namespace/load_name/version", - location=pe_types.LabwareOffsetLocation(slotName=DeckSlotName.SLOT_5), + location=pe_types.LegacyLabwareOffsetLocation(slotName=DeckSlotName.SLOT_5), + locationSequence=[ + pe_types.OnAddressableAreaOffsetLocationSequenceComponent( + addressableAreaName="5" + ) + ], vector=pe_types.LabwareOffsetVector(x=1, y=2, z=3), ) ] diff --git a/shared-data/python/opentrons_shared_data/deck/__init__.py b/shared-data/python/opentrons_shared_data/deck/__init__.py index 38607263418..f2136d6e97a 100644 --- a/shared-data/python/opentrons_shared_data/deck/__init__.py +++ b/shared-data/python/opentrons_shared_data/deck/__init__.py @@ -55,6 +55,11 @@ def load(name: str, version: "DeckSchemaVersion3") -> "DeckDefinitionV3": ... +@overload +def load(name: str) -> "DeckDefinitionV5": + ... + + def load(name: str, version: int = DEFAULT_DECK_DEFINITION_VERSION) -> "DeckDefinition": return json.loads( # type: ignore[no-any-return] load_shared_data(f"deck/definitions/{version}/{name}.json") From 6123b812f666f4e29e7c39036113f9517a5c4966 Mon Sep 17 00:00:00 2001 From: Sanniti Pimpley Date: Wed, 29 Jan 2025 13:56:39 -0500 Subject: [PATCH 18/22] feat(api): remove liquid classes feature flag, gate liquid classes behind 2.23 (#17378) Closes AUTH-1294 # Overview - Removes the `allowLiquidClasses` feature flag - Gates all liquid classes features (including `transfer_liquid()`, `distribute_liquid()`, `consolidate_liquid()`) behind PAPI version 2.23 - Updates tests ## Risk assessment Low. Makes the liquid classes feature available for use in the new API. But this work does not affect any existing APIs. --- api/release-notes-internal.md | 9 ++ api/src/opentrons/config/advanced_settings.py | 20 ++--- api/src/opentrons/config/feature_flags.py | 4 - .../protocol_api/instrument_context.py | 25 +----- .../protocol_api/protocol_context.py | 10 +-- .../test_advanced_settings_migration.py | 12 ++- .../protocol_api/test_instrument_context.py | 87 +------------------ .../protocol_api/test_protocol_context.py | 9 +- .../test_liquid_classes.py | 17 +--- .../test_transfer_with_liquid_classes.py | 18 ++-- 10 files changed, 42 insertions(+), 169 deletions(-) diff --git a/api/release-notes-internal.md b/api/release-notes-internal.md index bc5398781e4..7fb93059e15 100644 --- a/api/release-notes-internal.md +++ b/api/release-notes-internal.md @@ -2,6 +2,15 @@ For more details about this release, please see the full [technical change log][ [technical change log]: https://github.com/Opentrons/opentrons/releases +## Internal Release 2.4.0-alpha.1 + +This internal release, pulled from the `edge` branch, contains features being developed for 8.4.0. It's for internal testing only. + +### New Stuff In This Release (list in progress): + +- Python API version bumped to 2.23 +- Added liquid classes and new transfer functions + ## Internal Release 2.3.0-alpha.2 This internal release, pulled from the `edge` branch, contains features being developed for 8.3.0. It's for internal testing only. diff --git a/api/src/opentrons/config/advanced_settings.py b/api/src/opentrons/config/advanced_settings.py index 44cf5c0fcc4..2ec6f10c643 100644 --- a/api/src/opentrons/config/advanced_settings.py +++ b/api/src/opentrons/config/advanced_settings.py @@ -222,17 +222,6 @@ class Setting(NamedTuple): robot_type=[RobotTypeEnum.OT2, RobotTypeEnum.FLEX], internal_only=True, ), - SettingDefinition( - _id="allowLiquidClasses", - title="Allow the use of liquid classes", - description=( - "Do not enable." - " This is an Opentrons internal setting to allow using in-development" - " liquid classes." - ), - robot_type=[RobotTypeEnum.OT2, RobotTypeEnum.FLEX], - internal_only=True, - ), ] @@ -736,6 +725,14 @@ def _migrate35to36(previous: SettingsMap) -> SettingsMap: return newmap +def _migrate36to37(previous: SettingsMap) -> SettingsMap: + """Migrate to version 37 of the feature flags file. + + - Removes the allowLiquidClasses flag. + """ + return {k: v for k, v in previous.items() if "allowLiquidClasses" != k} + + _MIGRATIONS = [ _migrate0to1, _migrate1to2, @@ -773,6 +770,7 @@ def _migrate35to36(previous: SettingsMap) -> SettingsMap: _migrate33to34, _migrate34to35, _migrate35to36, + _migrate36to37, ] """ List of all migrations to apply, indexed by (version - 1). See _migrate below diff --git a/api/src/opentrons/config/feature_flags.py b/api/src/opentrons/config/feature_flags.py index 2164e66f90a..7eb40721511 100644 --- a/api/src/opentrons/config/feature_flags.py +++ b/api/src/opentrons/config/feature_flags.py @@ -78,7 +78,3 @@ def enable_performance_metrics(robot_type: RobotTypeEnum) -> bool: def oem_mode_enabled() -> bool: return advs.get_setting_with_env_overload("enableOEMMode", RobotTypeEnum.FLEX) - - -def allow_liquid_classes(robot_type: RobotTypeEnum) -> bool: - return advs.get_setting_with_env_overload("allowLiquidClasses", robot_type) diff --git a/api/src/opentrons/protocol_api/instrument_context.py b/api/src/opentrons/protocol_api/instrument_context.py index 6192b35670a..6bd93f27970 100644 --- a/api/src/opentrons/protocol_api/instrument_context.py +++ b/api/src/opentrons/protocol_api/instrument_context.py @@ -8,7 +8,6 @@ UnexpectedTipRemovalError, UnsupportedHardwareCommand, ) -from opentrons_shared_data.robot.types import RobotTypeEnum from opentrons.legacy_broker import LegacyBroker from opentrons.hardware_control.dev_types import PipetteDict @@ -38,7 +37,6 @@ from ._nozzle_layout import NozzleLayout from ._liquid import LiquidClass from . import labware, validation -from ..config import feature_flags from ..protocols.advanced_control.transfers.common import ( TransferTipPolicyV2, TransferTipPolicyV2Type, @@ -1509,6 +1507,7 @@ def _execute_transfer(self, plan: v1_transfer.TransferPlan) -> None: for cmd in plan: getattr(self, cmd["method"])(*cmd["args"], **cmd["kwargs"]) + @requires_version(2, 23) def transfer_liquid( self, liquid_class: LiquidClass, @@ -1528,13 +1527,6 @@ def transfer_liquid( TODO: Add args description. """ - if not feature_flags.allow_liquid_classes( - robot_type=RobotTypeEnum.robot_literal_to_enum( - self._protocol_core.robot_type - ) - ): - raise NotImplementedError("This method is not implemented.") - flat_sources_list = validation.ensure_valid_flat_wells_list_for_transfer_v2( source ) @@ -1604,6 +1596,7 @@ def transfer_liquid( ) return self + @requires_version(2, 23) def distribute_liquid( self, liquid_class: LiquidClass, @@ -1623,13 +1616,6 @@ def distribute_liquid( TODO: Add args description. """ - if not feature_flags.allow_liquid_classes( - robot_type=RobotTypeEnum.robot_literal_to_enum( - self._protocol_core.robot_type - ) - ): - raise NotImplementedError("This method is not implemented.") - if not isinstance(source, labware.Well): raise ValueError(f"Source should be a single Well but received {source}.") flat_dests_list = validation.ensure_valid_flat_wells_list_for_transfer_v2(dest) @@ -1689,6 +1675,7 @@ def distribute_liquid( ) return self + @requires_version(2, 23) def consolidate_liquid( self, liquid_class: LiquidClass, @@ -1708,12 +1695,6 @@ def consolidate_liquid( TODO: Add args description. """ - if not feature_flags.allow_liquid_classes( - robot_type=RobotTypeEnum.robot_literal_to_enum( - self._protocol_core.robot_type - ) - ): - raise NotImplementedError("This method is not implemented.") if not isinstance(dest, labware.Well): raise ValueError( f"Destination should be a single Well but received {dest}." diff --git a/api/src/opentrons/protocol_api/protocol_context.py b/api/src/opentrons/protocol_api/protocol_context.py index 1ea86aca893..f98d46f2e45 100644 --- a/api/src/opentrons/protocol_api/protocol_context.py +++ b/api/src/opentrons/protocol_api/protocol_context.py @@ -14,10 +14,8 @@ from opentrons_shared_data.labware.types import LabwareDefinition from opentrons_shared_data.pipette.types import PipetteNameType -from opentrons_shared_data.robot.types import RobotTypeEnum from opentrons.types import Mount, Location, DeckLocation, DeckSlotName, StagingSlotName -from opentrons.config import feature_flags from opentrons.legacy_broker import LegacyBroker from opentrons.hardware_control.modules.types import ( MagneticBlockModel, @@ -1354,17 +1352,13 @@ def define_liquid( display_color=display_color, ) + @requires_version(2, 23) def define_liquid_class( self, name: str, ) -> LiquidClass: """Define a liquid class for use in the protocol.""" - if feature_flags.allow_liquid_classes( - robot_type=RobotTypeEnum.robot_literal_to_enum(self._core.robot_type) - ): - return self._core.define_liquid_class(name=name) - else: - raise NotImplementedError("This method is not implemented.") + return self._core.define_liquid_class(name=name) @property @requires_version(2, 5) diff --git a/api/tests/opentrons/config/test_advanced_settings_migration.py b/api/tests/opentrons/config/test_advanced_settings_migration.py index a2bcf71a1fb..05101b53fc1 100644 --- a/api/tests/opentrons/config/test_advanced_settings_migration.py +++ b/api/tests/opentrons/config/test_advanced_settings_migration.py @@ -8,7 +8,7 @@ @pytest.fixture def migrated_file_version() -> int: - return 36 + return 37 # make sure to set a boolean value in default_file_settings only if @@ -30,7 +30,6 @@ def default_file_settings() -> Dict[str, Any]: "enableErrorRecoveryExperiments": None, "enableOEMMode": None, "enablePerformanceMetrics": None, - "allowLiquidClasses": None, } @@ -432,6 +431,13 @@ def v36_config(v35_config: Dict[str, Any]) -> Dict[str, Any]: return r +@pytest.fixture +def v37_config(v36_config: Dict[str, Any]) -> Dict[str, Any]: + r = {k: v for k, v in v36_config.items() if k != "allowLiquidClasses"} + r["_version"] = 37 + return r + + @pytest.fixture( scope="session", params=[ @@ -473,6 +479,7 @@ def v36_config(v35_config: Dict[str, Any]) -> Dict[str, Any]: lazy_fixture("v34_config"), lazy_fixture("v35_config"), lazy_fixture("v36_config"), + lazy_fixture("v37_config"), ], ) def old_settings(request: SubRequest) -> Dict[str, Any]: @@ -563,5 +570,4 @@ def test_ensures_config() -> None: "enableErrorRecoveryExperiments": None, "enableOEMMode": None, "enablePerformanceMetrics": None, - "allowLiquidClasses": None, } diff --git a/api/tests/opentrons/protocol_api/test_instrument_context.py b/api/tests/opentrons/protocol_api/test_instrument_context.py index 7fad487086a..fc3d1867634 100644 --- a/api/tests/opentrons/protocol_api/test_instrument_context.py +++ b/api/tests/opentrons/protocol_api/test_instrument_context.py @@ -10,7 +10,6 @@ from decoy import Decoy from pytest_lazyfixture import lazy_fixture # type: ignore[import-untyped] -from opentrons.config import feature_flags as ff from opentrons.protocol_engine.commands.pipetting_common import LiquidNotFoundError from opentrons.protocol_engine.errors.error_occurrence import ( ProtocolCommandFailedError, @@ -63,7 +62,7 @@ from opentrons_shared_data.liquid_classes.liquid_class_definition import ( LiquidClassSchemaV1, ) -from opentrons_shared_data.robot.types import RobotTypeEnum, RobotType +from opentrons_shared_data.robot.types import RobotType from . import versions_at_or_above, versions_between @@ -1737,7 +1736,6 @@ def test_transfer_liquid_raises_for_invalid_locations( decoy: Decoy, mock_protocol_core: ProtocolCore, subject: InstrumentContext, - mock_feature_flags: None, robot_type: RobotType, minimal_liquid_class_def2: LiquidClassSchemaV1, ) -> None: @@ -1745,9 +1743,6 @@ def test_transfer_liquid_raises_for_invalid_locations( test_liq_class = LiquidClass.create(minimal_liquid_class_def2) mock_well = decoy.mock(cls=Well) decoy.when(mock_protocol_core.robot_type).then_return(robot_type) - decoy.when( - ff.allow_liquid_classes(RobotTypeEnum.robot_literal_to_enum(robot_type)) - ).then_return(True) decoy.when( mock_validation.ensure_valid_flat_wells_list_for_transfer_v2([mock_well]) ).then_raise(ValueError("Oh no")) @@ -1765,7 +1760,6 @@ def test_transfer_liquid_raises_for_unequal_source_and_dest( decoy: Decoy, mock_protocol_core: ProtocolCore, subject: InstrumentContext, - mock_feature_flags: None, robot_type: RobotType, minimal_liquid_class_def2: LiquidClassSchemaV1, ) -> None: @@ -1773,9 +1767,6 @@ def test_transfer_liquid_raises_for_unequal_source_and_dest( test_liq_class = LiquidClass.create(minimal_liquid_class_def2) mock_well = decoy.mock(cls=Well) decoy.when(mock_protocol_core.robot_type).then_return(robot_type) - decoy.when( - ff.allow_liquid_classes(RobotTypeEnum.robot_literal_to_enum(robot_type)) - ).then_return(True) decoy.when( mock_validation.ensure_valid_flat_wells_list_for_transfer_v2(mock_well) ).then_return([mock_well, mock_well]) @@ -1795,7 +1786,6 @@ def test_transfer_liquid_raises_for_non_liquid_handling_locations( decoy: Decoy, mock_protocol_core: ProtocolCore, subject: InstrumentContext, - mock_feature_flags: None, robot_type: RobotType, minimal_liquid_class_def2: LiquidClassSchemaV1, ) -> None: @@ -1803,9 +1793,6 @@ def test_transfer_liquid_raises_for_non_liquid_handling_locations( test_liq_class = LiquidClass.create(minimal_liquid_class_def2) mock_well = decoy.mock(cls=Well) decoy.when(mock_protocol_core.robot_type).then_return(robot_type) - decoy.when( - ff.allow_liquid_classes(RobotTypeEnum.robot_literal_to_enum(robot_type)) - ).then_return(True) decoy.when( mock_validation.ensure_valid_flat_wells_list_for_transfer_v2([mock_well]) ).then_return([mock_well]) @@ -1825,7 +1812,6 @@ def test_transfer_liquid_raises_for_bad_tip_policy( decoy: Decoy, mock_protocol_core: ProtocolCore, subject: InstrumentContext, - mock_feature_flags: None, robot_type: RobotType, minimal_liquid_class_def2: LiquidClassSchemaV1, ) -> None: @@ -1833,9 +1819,6 @@ def test_transfer_liquid_raises_for_bad_tip_policy( test_liq_class = LiquidClass.create(minimal_liquid_class_def2) mock_well = decoy.mock(cls=Well) decoy.when(mock_protocol_core.robot_type).then_return(robot_type) - decoy.when( - ff.allow_liquid_classes(RobotTypeEnum.robot_literal_to_enum(robot_type)) - ).then_return(True) decoy.when( mock_validation.ensure_valid_flat_wells_list_for_transfer_v2([mock_well]) ).then_return([mock_well]) @@ -1857,7 +1840,6 @@ def test_transfer_liquid_raises_for_no_tip( decoy: Decoy, mock_protocol_core: ProtocolCore, subject: InstrumentContext, - mock_feature_flags: None, robot_type: RobotType, minimal_liquid_class_def2: LiquidClassSchemaV1, ) -> None: @@ -1865,9 +1847,6 @@ def test_transfer_liquid_raises_for_no_tip( test_liq_class = LiquidClass.create(minimal_liquid_class_def2) mock_well = decoy.mock(cls=Well) decoy.when(mock_protocol_core.robot_type).then_return(robot_type) - decoy.when( - ff.allow_liquid_classes(RobotTypeEnum.robot_literal_to_enum(robot_type)) - ).then_return(True) decoy.when( mock_validation.ensure_valid_flat_wells_list_for_transfer_v2([mock_well]) ).then_return([mock_well]) @@ -1890,7 +1869,6 @@ def test_transfer_liquid_raises_if_tip_has_liquid( mock_protocol_core: ProtocolCore, mock_instrument_core: InstrumentCore, subject: InstrumentContext, - mock_feature_flags: None, robot_type: RobotType, minimal_liquid_class_def2: LiquidClassSchemaV1, ) -> None: @@ -1903,9 +1881,6 @@ def test_transfer_liquid_raises_if_tip_has_liquid( subject.tip_racks = tip_racks decoy.when(mock_protocol_core.robot_type).then_return(robot_type) - decoy.when( - ff.allow_liquid_classes(RobotTypeEnum.robot_literal_to_enum(robot_type)) - ).then_return(True) decoy.when( mock_validation.ensure_valid_flat_wells_list_for_transfer_v2([mock_well]) ).then_return([mock_well]) @@ -1939,7 +1914,6 @@ def test_transfer_liquid_delegates_to_engine_core( mock_protocol_core: ProtocolCore, mock_instrument_core: InstrumentCore, subject: InstrumentContext, - mock_feature_flags: None, robot_type: RobotType, minimal_liquid_class_def2: LiquidClassSchemaV1, ) -> None: @@ -1953,9 +1927,6 @@ def test_transfer_liquid_delegates_to_engine_core( subject._tip_racks = tip_racks decoy.when(mock_protocol_core.robot_type).then_return(robot_type) - decoy.when( - ff.allow_liquid_classes(RobotTypeEnum.robot_literal_to_enum(robot_type)) - ).then_return(True) decoy.when( mock_validation.ensure_valid_flat_wells_list_for_transfer_v2([mock_well]) ).then_return([mock_well]) @@ -1996,7 +1967,6 @@ def test_distribute_liquid_raises_for_invalid_locations( decoy: Decoy, mock_protocol_core: ProtocolCore, subject: InstrumentContext, - mock_feature_flags: None, robot_type: RobotType, minimal_liquid_class_def2: LiquidClassSchemaV1, ) -> None: @@ -2004,9 +1974,6 @@ def test_distribute_liquid_raises_for_invalid_locations( test_liq_class = LiquidClass.create(minimal_liquid_class_def2) mock_well = decoy.mock(cls=Well) decoy.when(mock_protocol_core.robot_type).then_return(robot_type) - decoy.when( - ff.allow_liquid_classes(RobotTypeEnum.robot_literal_to_enum(robot_type)) - ).then_return(True) decoy.when( mock_validation.ensure_valid_flat_wells_list_for_transfer_v2([[mock_well]]) ).then_raise(ValueError("Oh no")) @@ -2031,7 +1998,6 @@ def test_distribute_liquid_raises_if_more_than_one_source( decoy: Decoy, mock_protocol_core: ProtocolCore, subject: InstrumentContext, - mock_feature_flags: None, robot_type: RobotType, minimal_liquid_class_def2: LiquidClassSchemaV1, ) -> None: @@ -2039,9 +2005,6 @@ def test_distribute_liquid_raises_if_more_than_one_source( test_liq_class = LiquidClass.create(minimal_liquid_class_def2) mock_well = decoy.mock(cls=Well) decoy.when(mock_protocol_core.robot_type).then_return(robot_type) - decoy.when( - ff.allow_liquid_classes(RobotTypeEnum.robot_literal_to_enum(robot_type)) - ).then_return(True) with pytest.raises(ValueError, match="Source should be a single Well"): subject.distribute_liquid( liquid_class=test_liq_class, volume=10, source=[mock_well, mock_well], dest=[mock_well] # type: ignore @@ -2053,7 +2016,6 @@ def test_distribute_liquid_raises_for_non_liquid_handling_locations( decoy: Decoy, mock_protocol_core: ProtocolCore, subject: InstrumentContext, - mock_feature_flags: None, robot_type: RobotType, minimal_liquid_class_def2: LiquidClassSchemaV1, ) -> None: @@ -2061,9 +2023,6 @@ def test_distribute_liquid_raises_for_non_liquid_handling_locations( test_liq_class = LiquidClass.create(minimal_liquid_class_def2) mock_well = decoy.mock(cls=Well) decoy.when(mock_protocol_core.robot_type).then_return(robot_type) - decoy.when( - ff.allow_liquid_classes(RobotTypeEnum.robot_literal_to_enum(robot_type)) - ).then_return(True) decoy.when( mock_validation.ensure_valid_flat_wells_list_for_transfer_v2([mock_well]) ).then_return([mock_well]) @@ -2083,7 +2042,6 @@ def test_distribute_liquid_raises_for_bad_tip_policy( decoy: Decoy, mock_protocol_core: ProtocolCore, subject: InstrumentContext, - mock_feature_flags: None, robot_type: RobotType, minimal_liquid_class_def2: LiquidClassSchemaV1, ) -> None: @@ -2091,9 +2049,6 @@ def test_distribute_liquid_raises_for_bad_tip_policy( test_liq_class = LiquidClass.create(minimal_liquid_class_def2) mock_well = decoy.mock(cls=Well) decoy.when(mock_protocol_core.robot_type).then_return(robot_type) - decoy.when( - ff.allow_liquid_classes(RobotTypeEnum.robot_literal_to_enum(robot_type)) - ).then_return(True) decoy.when( mock_validation.ensure_valid_flat_wells_list_for_transfer_v2([mock_well]) ).then_return([mock_well]) @@ -2115,7 +2070,6 @@ def test_distribute_liquid_raises_for_no_tip( decoy: Decoy, mock_protocol_core: ProtocolCore, subject: InstrumentContext, - mock_feature_flags: None, robot_type: RobotType, minimal_liquid_class_def2: LiquidClassSchemaV1, ) -> None: @@ -2123,9 +2077,6 @@ def test_distribute_liquid_raises_for_no_tip( test_liq_class = LiquidClass.create(minimal_liquid_class_def2) mock_well = decoy.mock(cls=Well) decoy.when(mock_protocol_core.robot_type).then_return(robot_type) - decoy.when( - ff.allow_liquid_classes(RobotTypeEnum.robot_literal_to_enum(robot_type)) - ).then_return(True) decoy.when( mock_validation.ensure_valid_flat_wells_list_for_transfer_v2([mock_well]) ).then_return([mock_well]) @@ -2148,7 +2099,6 @@ def test_distribute_liquid_raises_if_tip_has_liquid( mock_protocol_core: ProtocolCore, mock_instrument_core: InstrumentCore, subject: InstrumentContext, - mock_feature_flags: None, robot_type: RobotType, minimal_liquid_class_def2: LiquidClassSchemaV1, ) -> None: @@ -2161,9 +2111,6 @@ def test_distribute_liquid_raises_if_tip_has_liquid( subject.tip_racks = tip_racks decoy.when(mock_protocol_core.robot_type).then_return(robot_type) - decoy.when( - ff.allow_liquid_classes(RobotTypeEnum.robot_literal_to_enum(robot_type)) - ).then_return(True) decoy.when( mock_validation.ensure_valid_flat_wells_list_for_transfer_v2([mock_well]) ).then_return([mock_well]) @@ -2197,7 +2144,6 @@ def test_distribute_liquid_delegates_to_engine_core( mock_protocol_core: ProtocolCore, mock_instrument_core: InstrumentCore, subject: InstrumentContext, - mock_feature_flags: None, robot_type: RobotType, minimal_liquid_class_def2: LiquidClassSchemaV1, ) -> None: @@ -2211,9 +2157,6 @@ def test_distribute_liquid_delegates_to_engine_core( subject._tip_racks = tip_racks decoy.when(mock_protocol_core.robot_type).then_return(robot_type) - decoy.when( - ff.allow_liquid_classes(RobotTypeEnum.robot_literal_to_enum(robot_type)) - ).then_return(True) decoy.when( mock_validation.ensure_valid_flat_wells_list_for_transfer_v2([mock_well]) ).then_return([mock_well]) @@ -2254,7 +2197,6 @@ def test_consolidate_liquid_raises_for_invalid_locations( decoy: Decoy, mock_protocol_core: ProtocolCore, subject: InstrumentContext, - mock_feature_flags: None, robot_type: RobotType, minimal_liquid_class_def2: LiquidClassSchemaV1, ) -> None: @@ -2262,9 +2204,6 @@ def test_consolidate_liquid_raises_for_invalid_locations( test_liq_class = LiquidClass.create(minimal_liquid_class_def2) mock_well = decoy.mock(cls=Well) decoy.when(mock_protocol_core.robot_type).then_return(robot_type) - decoy.when( - ff.allow_liquid_classes(RobotTypeEnum.robot_literal_to_enum(robot_type)) - ).then_return(True) decoy.when( mock_validation.ensure_valid_flat_wells_list_for_transfer_v2([[mock_well]]) ).then_raise(ValueError("Oh no")) @@ -2289,7 +2228,6 @@ def test_consolidate_liquid_raises_if_more_than_one_destination( decoy: Decoy, mock_protocol_core: ProtocolCore, subject: InstrumentContext, - mock_feature_flags: None, robot_type: RobotType, minimal_liquid_class_def2: LiquidClassSchemaV1, ) -> None: @@ -2297,9 +2235,6 @@ def test_consolidate_liquid_raises_if_more_than_one_destination( test_liq_class = LiquidClass.create(minimal_liquid_class_def2) mock_well = decoy.mock(cls=Well) decoy.when(mock_protocol_core.robot_type).then_return(robot_type) - decoy.when( - ff.allow_liquid_classes(RobotTypeEnum.robot_literal_to_enum(robot_type)) - ).then_return(True) with pytest.raises(ValueError, match="Destination should be a single Well"): subject.consolidate_liquid( liquid_class=test_liq_class, @@ -2314,7 +2249,6 @@ def test_consolidate_liquid_raises_for_non_liquid_handling_locations( decoy: Decoy, mock_protocol_core: ProtocolCore, subject: InstrumentContext, - mock_feature_flags: None, robot_type: RobotType, minimal_liquid_class_def2: LiquidClassSchemaV1, ) -> None: @@ -2322,9 +2256,6 @@ def test_consolidate_liquid_raises_for_non_liquid_handling_locations( test_liq_class = LiquidClass.create(minimal_liquid_class_def2) mock_well = decoy.mock(cls=Well) decoy.when(mock_protocol_core.robot_type).then_return(robot_type) - decoy.when( - ff.allow_liquid_classes(RobotTypeEnum.robot_literal_to_enum(robot_type)) - ).then_return(True) decoy.when( mock_validation.ensure_valid_flat_wells_list_for_transfer_v2([mock_well]) ).then_return([mock_well]) @@ -2344,7 +2275,6 @@ def test_consolidate_liquid_raises_for_bad_tip_policy( decoy: Decoy, mock_protocol_core: ProtocolCore, subject: InstrumentContext, - mock_feature_flags: None, robot_type: RobotType, minimal_liquid_class_def2: LiquidClassSchemaV1, ) -> None: @@ -2352,9 +2282,6 @@ def test_consolidate_liquid_raises_for_bad_tip_policy( test_liq_class = LiquidClass.create(minimal_liquid_class_def2) mock_well = decoy.mock(cls=Well) decoy.when(mock_protocol_core.robot_type).then_return(robot_type) - decoy.when( - ff.allow_liquid_classes(RobotTypeEnum.robot_literal_to_enum(robot_type)) - ).then_return(True) decoy.when( mock_validation.ensure_valid_flat_wells_list_for_transfer_v2([mock_well]) ).then_return([mock_well]) @@ -2376,7 +2303,6 @@ def test_consolidate_liquid_raises_for_no_tip( decoy: Decoy, mock_protocol_core: ProtocolCore, subject: InstrumentContext, - mock_feature_flags: None, robot_type: RobotType, minimal_liquid_class_def2: LiquidClassSchemaV1, ) -> None: @@ -2384,9 +2310,6 @@ def test_consolidate_liquid_raises_for_no_tip( test_liq_class = LiquidClass.create(minimal_liquid_class_def2) mock_well = decoy.mock(cls=Well) decoy.when(mock_protocol_core.robot_type).then_return(robot_type) - decoy.when( - ff.allow_liquid_classes(RobotTypeEnum.robot_literal_to_enum(robot_type)) - ).then_return(True) decoy.when( mock_validation.ensure_valid_flat_wells_list_for_transfer_v2([mock_well]) ).then_return([mock_well]) @@ -2409,7 +2332,6 @@ def test_consolidate_liquid_raises_if_tip_has_liquid( mock_protocol_core: ProtocolCore, mock_instrument_core: InstrumentCore, subject: InstrumentContext, - mock_feature_flags: None, robot_type: RobotType, minimal_liquid_class_def2: LiquidClassSchemaV1, ) -> None: @@ -2422,9 +2344,6 @@ def test_consolidate_liquid_raises_if_tip_has_liquid( subject.tip_racks = tip_racks decoy.when(mock_protocol_core.robot_type).then_return(robot_type) - decoy.when( - ff.allow_liquid_classes(RobotTypeEnum.robot_literal_to_enum(robot_type)) - ).then_return(True) decoy.when( mock_validation.ensure_valid_flat_wells_list_for_transfer_v2([mock_well]) ).then_return([mock_well]) @@ -2458,7 +2377,6 @@ def test_consolidate_liquid_delegates_to_engine_core( mock_protocol_core: ProtocolCore, mock_instrument_core: InstrumentCore, subject: InstrumentContext, - mock_feature_flags: None, robot_type: RobotType, minimal_liquid_class_def2: LiquidClassSchemaV1, ) -> None: @@ -2472,9 +2390,6 @@ def test_consolidate_liquid_delegates_to_engine_core( subject._tip_racks = tip_racks decoy.when(mock_protocol_core.robot_type).then_return(robot_type) - decoy.when( - ff.allow_liquid_classes(RobotTypeEnum.robot_literal_to_enum(robot_type)) - ).then_return(True) decoy.when( mock_validation.ensure_valid_flat_wells_list_for_transfer_v2([mock_well]) ).then_return([mock_well]) diff --git a/api/tests/opentrons/protocol_api/test_protocol_context.py b/api/tests/opentrons/protocol_api/test_protocol_context.py index 8e944d62cac..ebe6734a539 100644 --- a/api/tests/opentrons/protocol_api/test_protocol_context.py +++ b/api/tests/opentrons/protocol_api/test_protocol_context.py @@ -7,11 +7,10 @@ from opentrons_shared_data.pipette.types import PipetteNameType from opentrons_shared_data.labware.types import LabwareDefinition as LabwareDefDict -from opentrons_shared_data.robot.types import RobotTypeEnum, RobotType +from opentrons_shared_data.robot.types import RobotType from opentrons.protocol_api._liquid import LiquidClass from opentrons.types import Mount, DeckSlotName, StagingSlotName -from opentrons.config import feature_flags as ff from opentrons.protocol_api import OFF_DECK from opentrons.legacy_broker import LegacyBroker from opentrons.hardware_control.modules.types import ( @@ -1456,7 +1455,6 @@ def test_define_liquid_class( mock_core: ProtocolCore, subject: ProtocolContext, robot_type: RobotType, - mock_feature_flags: None, ) -> None: """It should create the liquid class definition.""" expected_liquid_class = LiquidClass( @@ -1466,14 +1464,11 @@ def test_define_liquid_class( expected_liquid_class ) decoy.when(mock_core.robot_type).then_return(robot_type) - decoy.when( - ff.allow_liquid_classes(RobotTypeEnum.robot_literal_to_enum(robot_type)) - ).then_return(True) assert subject.define_liquid_class("volatile_90") == expected_liquid_class def test_bundled_data( - decoy: Decoy, mock_core_map: LoadedCoreMap, mock_deck: Deck, mock_core: ProtocolCore + mock_core_map: LoadedCoreMap, mock_deck: Deck, mock_core: ProtocolCore ) -> None: """It should return bundled data.""" subject = ProtocolContext( diff --git a/api/tests/opentrons/protocol_api_integration/test_liquid_classes.py b/api/tests/opentrons/protocol_api_integration/test_liquid_classes.py index 54112941c4c..83b53f01e1a 100644 --- a/api/tests/opentrons/protocol_api_integration/test_liquid_classes.py +++ b/api/tests/opentrons/protocol_api_integration/test_liquid_classes.py @@ -1,23 +1,17 @@ """Tests for the APIs around liquid classes.""" import pytest -from decoy import Decoy -from opentrons_shared_data.robot.types import RobotTypeEnum from opentrons.protocol_api import ProtocolContext -from opentrons.config import feature_flags as ff @pytest.mark.ot3_only @pytest.mark.parametrize( - "simulated_protocol_context", [("2.20", "Flex")], indirect=True + "simulated_protocol_context", [("2.23", "Flex")], indirect=True ) def test_liquid_class_creation_and_property_fetching( - decoy: Decoy, - mock_feature_flags: None, simulated_protocol_context: ProtocolContext, ) -> None: """It should create the liquid class and provide access to its properties.""" - decoy.when(ff.allow_liquid_classes(RobotTypeEnum.FLEX)).then_return(True) pipette_load_name = "flex_8channel_50" simulated_protocol_context.load_instrument(pipette_load_name, mount="left") tiprack = simulated_protocol_context.load_labware( @@ -51,12 +45,3 @@ def test_liquid_class_creation_and_property_fetching( with pytest.raises(ValueError, match="Liquid class definition not found"): simulated_protocol_context.define_liquid_class("non-existent-liquid") - - -@pytest.mark.parametrize( - "simulated_protocol_context", [("2.20", "OT-2")], indirect=True -) -def test_liquid_class_feature_flag(simulated_protocol_context: ProtocolContext) -> None: - """It should raise a not implemented error without the allowLiquidClass flag set.""" - with pytest.raises(NotImplementedError): - simulated_protocol_context.define_liquid_class("water") diff --git a/api/tests/opentrons/protocol_api_integration/test_transfer_with_liquid_classes.py b/api/tests/opentrons/protocol_api_integration/test_transfer_with_liquid_classes.py index 24a5efc0dab..ba3d3facd6a 100644 --- a/api/tests/opentrons/protocol_api_integration/test_transfer_with_liquid_classes.py +++ b/api/tests/opentrons/protocol_api_integration/test_transfer_with_liquid_classes.py @@ -1,11 +1,8 @@ """Tests for the transfer APIs using liquid classes.""" import pytest import mock -from decoy import Decoy -from opentrons_shared_data.robot.types import RobotTypeEnum from opentrons.protocol_api import ProtocolContext -from opentrons.config import feature_flags as ff from opentrons.protocol_api.core.engine import InstrumentCore from opentrons.protocol_api.core.engine.transfer_components_executor import ( TransferType, @@ -15,10 +12,10 @@ @pytest.mark.ot3_only @pytest.mark.parametrize( - "simulated_protocol_context", [("2.20", "Flex")], indirect=True + "simulated_protocol_context", [("2.23", "Flex")], indirect=True ) def test_water_transfer_with_volume_more_than_tip_max( - decoy: Decoy, mock_feature_flags: None, simulated_protocol_context: ProtocolContext + simulated_protocol_context: ProtocolContext, ) -> None: """It should run the transfer steps without any errors. @@ -26,7 +23,6 @@ def test_water_transfer_with_volume_more_than_tip_max( analyze successfully. It doesn't check whether the steps are as expected. That will be covered in analysis snapshot tests. """ - decoy.when(ff.allow_liquid_classes(RobotTypeEnum.FLEX)).then_return(True) trash = simulated_protocol_context.load_trash_bin("A3") tiprack = simulated_protocol_context.load_labware( "opentrons_flex_96_tiprack_50ul", "D1" @@ -88,10 +84,10 @@ def test_water_transfer_with_volume_more_than_tip_max( @pytest.mark.ot3_only @pytest.mark.parametrize( - "simulated_protocol_context", [("2.20", "Flex")], indirect=True + "simulated_protocol_context", [("2.23", "Flex")], indirect=True ) def test_order_of_water_transfer_steps( - decoy: Decoy, mock_feature_flags: None, simulated_protocol_context: ProtocolContext + simulated_protocol_context: ProtocolContext, ) -> None: """It should run the transfer steps without any errors. @@ -99,7 +95,6 @@ def test_order_of_water_transfer_steps( analyze successfully. It doesn't check whether the steps are as expected. That will be covered in analysis snapshot tests. """ - decoy.when(ff.allow_liquid_classes(RobotTypeEnum.FLEX)).then_return(True) trash = simulated_protocol_context.load_trash_bin("A3") tiprack = simulated_protocol_context.load_labware( "opentrons_flex_96_tiprack_50ul", "D1" @@ -239,10 +234,10 @@ def test_order_of_water_transfer_steps( @pytest.mark.ot3_only @pytest.mark.parametrize( - "simulated_protocol_context", [("2.20", "Flex")], indirect=True + "simulated_protocol_context", [("2.23", "Flex")], indirect=True ) def test_order_of_water_transfer_steps_with_no_new_tips( - decoy: Decoy, mock_feature_flags: None, simulated_protocol_context: ProtocolContext + simulated_protocol_context: ProtocolContext, ) -> None: """It should run the transfer steps without any errors. @@ -250,7 +245,6 @@ def test_order_of_water_transfer_steps_with_no_new_tips( analyze successfully. It doesn't check whether the steps are as expected. That will be covered in analysis snapshot tests. """ - decoy.when(ff.allow_liquid_classes(RobotTypeEnum.FLEX)).then_return(True) trash = simulated_protocol_context.load_trash_bin("A3") tiprack = simulated_protocol_context.load_labware( "opentrons_flex_96_tiprack_50ul", "D1" From 8004d5948815e8202bdfbf4b27048b08c8151bb9 Mon Sep 17 00:00:00 2001 From: Sarah Breen Date: Wed, 29 Jan 2025 15:49:09 -0500 Subject: [PATCH 19/22] feat(app): Stub out flex stacker in deck config (#17381) Fix EXEC-1087 --- api-client/src/modules/api-types.ts | 1 + .../AddFixtureModal.tsx | 90 +++++++++++++---- .../DeckConfigurator/FlexStackerFixture.tsx | 96 +++++++++++++++++++ .../hardware-sim/DeckConfigurator/index.tsx | 29 +++++- shared-data/js/constants.ts | 10 ++ shared-data/js/fixtures.ts | 26 ++++- 6 files changed, 230 insertions(+), 22 deletions(-) create mode 100644 components/src/hardware-sim/DeckConfigurator/FlexStackerFixture.tsx diff --git a/api-client/src/modules/api-types.ts b/api-client/src/modules/api-types.ts index 17c3bd53fcf..d4755b69f57 100644 --- a/api-client/src/modules/api-types.ts +++ b/api-client/src/modules/api-types.ts @@ -10,6 +10,7 @@ interface PhysicalPort { port: number hub: boolean portGroup: PortGroup + hubPort?: number } type ModuleOffsetSource = diff --git a/app/src/organisms/DeviceDetailsDeckConfiguration/AddFixtureModal.tsx b/app/src/organisms/DeviceDetailsDeckConfiguration/AddFixtureModal.tsx index b4b8f462d7f..f6d633737cf 100644 --- a/app/src/organisms/DeviceDetailsDeckConfiguration/AddFixtureModal.tsx +++ b/app/src/organisms/DeviceDetailsDeckConfiguration/AddFixtureModal.tsx @@ -47,6 +47,10 @@ import { TRASH_BIN_ADAPTER_FIXTURE, WASTE_CHUTE_CUTOUT, WASTE_CHUTE_FIXTURES, + FLEX_STACKER_MODULE_V1, + FLEX_STACKER_V1_FIXTURE, + FLEX_STACKER_WITH_WASTE_CHUTE_ADAPTER_COVERED_FIXTURE, + FLEX_STACKER_WTIH_WASTE_CHUTE_ADAPTER_NO_COVER_FIXTURE, } from '@opentrons/shared-data' import { ODD_FOCUS_VISIBLE } from '/app/atoms/buttons/constants' @@ -249,6 +253,52 @@ export function AddFixtureModal({ ] } } + if ( + cutoutId === 'cutoutD3' && + unconfiguredMods.some(m => m.moduleModel === FLEX_STACKER_MODULE_V1) + ) { + const unconfiguredFlexStackers: CutoutConfig[][] = [] + unconfiguredMods + .filter(mod => mod.moduleModel === FLEX_STACKER_MODULE_V1) + .forEach(mod => { + unconfiguredFlexStackers.push([ + { + cutoutId, + cutoutFixtureId: FLEX_STACKER_V1_FIXTURE, + opentronsModuleSerialNumber: mod.serialNumber, + }, + ]) + unconfiguredFlexStackers.push([ + { + cutoutId, + cutoutFixtureId: FLEX_STACKER_WITH_WASTE_CHUTE_ADAPTER_COVERED_FIXTURE, + opentronsModuleSerialNumber: mod.serialNumber, + }, + ]) + unconfiguredFlexStackers.push([ + { + cutoutId, + cutoutFixtureId: FLEX_STACKER_WTIH_WASTE_CHUTE_ADAPTER_NO_COVER_FIXTURE, + opentronsModuleSerialNumber: mod.serialNumber, + }, + ]) + }) + availableOptions.push(...unconfiguredFlexStackers) + } else if ( + STAGING_AREA_CUTOUTS.includes(cutoutId) && + unconfiguredMods.some(m => m.moduleModel === FLEX_STACKER_MODULE_V1) + ) { + const unconfiguredFlexStackers = unconfiguredMods + .filter(mod => mod.moduleModel === FLEX_STACKER_MODULE_V1) + .map(mod => [ + { + cutoutId, + cutoutFixtureId: FLEX_STACKER_V1_FIXTURE, + opentronsModuleSerialNumber: mod.serialNumber, + }, + ]) + availableOptions = [...availableOptions, ...unconfiguredFlexStackers] + } } else if (optionStage === 'wasteChuteOptions') { availableOptions = WASTE_CHUTE_FIXTURES.map(fixture => [ { @@ -315,22 +365,30 @@ export function AddFixtureModal({ closeModal() } - const fixtureOptions = availableOptions.map(cutoutConfigs => ( - m.serialNumber === cutoutConfigs[0].opentronsModuleSerialNumber - )?.usbPort.port - )} - buttonText={t('add')} - onClickHandler={() => { - handleAddFixture(cutoutConfigs) - }} - isOnDevice={isOnDevice} - /> - )) + const fixtureOptions = availableOptions.map(cutoutConfigs => { + const usbPort = (modulesData?.data ?? []).find( + m => m.serialNumber === cutoutConfigs[0].opentronsModuleSerialNumber + )?.usbPort + const portDisplay = + usbPort?.hubPort != null + ? `${usbPort.port}.${usbPort.hubPort}` + : usbPort?.port + + return ( + { + handleAddFixture(cutoutConfigs) + }} + isOnDevice={isOnDevice} + /> + ) + }) return ( <> diff --git a/components/src/hardware-sim/DeckConfigurator/FlexStackerFixture.tsx b/components/src/hardware-sim/DeckConfigurator/FlexStackerFixture.tsx new file mode 100644 index 00000000000..55866fe1c8d --- /dev/null +++ b/components/src/hardware-sim/DeckConfigurator/FlexStackerFixture.tsx @@ -0,0 +1,96 @@ +import { Icon } from '../../icons' +import { Btn, Text } from '../../primitives' +import { TYPOGRAPHY } from '../../ui-style-constants' +import { COLORS } from '../../helix-design-system' +import { RobotCoordsForeignObject } from '../Deck/RobotCoordsForeignObject' +import { + COLUMN_3_X_ADJUSTMENT, + CONFIG_STYLE_EDITABLE, + CONFIG_STYLE_READ_ONLY, + FIXTURE_HEIGHT, + STAGING_AREA_FIXTURE_WIDTH, + Y_ADJUSTMENT, + CONFIG_STYLE_SELECTED, +} from './constants' + +import type { + CutoutFixtureId, + CutoutId, + DeckDefinition, +} from '@opentrons/shared-data' + +interface FlexStackerFixtureProps { + deckDefinition: DeckDefinition + fixtureLocation: CutoutId + cutoutFixtureId: CutoutFixtureId + hasWasteChute: boolean + handleClickRemove?: ( + fixtureLocation: CutoutId, + cutoutFixtureId: CutoutFixtureId + ) => void + selected?: boolean +} + +const FLEX_STACKER_FIXTURE_DISPLAY_NAME = 'Stacker' +const FLEX_STACKER_WASTE_CHUTE_DISPLAY_NAME = 'Stacker + Waste chute' + +export function FlexStackerFixture( + props: FlexStackerFixtureProps +): JSX.Element { + const { + deckDefinition, + handleClickRemove, + fixtureLocation, + cutoutFixtureId, + hasWasteChute, + selected = false, + } = props + + const cutoutDef = deckDefinition.locations.cutouts.find( + cutout => cutout.id === fixtureLocation + ) + + /** + * deck definition cutout position is the position of the single slot located within that cutout + * so, to get the position of the cutout itself we must add an adjustment to the slot position + * the adjustment for x is different for right side/left side + */ + const [xSlotPosition = 0, ySlotPosition = 0] = cutoutDef?.position ?? [] + + const x = xSlotPosition + COLUMN_3_X_ADJUSTMENT + + const y = ySlotPosition + Y_ADJUSTMENT + + const editableStyle = selected ? CONFIG_STYLE_SELECTED : CONFIG_STYLE_EDITABLE + return ( + + { + handleClickRemove(fixtureLocation, cutoutFixtureId) + } + : () => {} + } + > + + {hasWasteChute + ? FLEX_STACKER_WASTE_CHUTE_DISPLAY_NAME + : FLEX_STACKER_FIXTURE_DISPLAY_NAME} + + {handleClickRemove != null ? ( + + ) : null} + + + ) +} diff --git a/components/src/hardware-sim/DeckConfigurator/index.tsx b/components/src/hardware-sim/DeckConfigurator/index.tsx index 4a90a182cee..27a6ff46886 100644 --- a/components/src/hardware-sim/DeckConfigurator/index.tsx +++ b/components/src/hardware-sim/DeckConfigurator/index.tsx @@ -11,6 +11,8 @@ import { TEMPERATURE_MODULE_V2_FIXTURE, MAGNETIC_BLOCK_V1_FIXTURE, ABSORBANCE_READER_V1_FIXTURE, + FLEX_STACKER_V1_FIXTURE, + FLEX_STACKER_FIXTURES, STAGING_AREA_SLOT_WITH_MAGNETIC_BLOCK_V1_FIXTURE, THERMOCYCLER_MODULE_CUTOUTS, } from '@opentrons/shared-data' @@ -24,6 +26,12 @@ import { StagingAreaConfigFixture } from './StagingAreaConfigFixture' import { TrashBinConfigFixture } from './TrashBinConfigFixture' import { WasteChuteConfigFixture } from './WasteChuteConfigFixture' import { StaticFixture } from './StaticFixture' +import { TemperatureModuleFixture } from './TemperatureModuleFixture' +import { HeaterShakerFixture } from './HeaterShakerFixture' +import { MagneticBlockFixture } from './MagneticBlockFixture' +import { ThermocyclerFixture } from './ThermocyclerFixture' +import { AbsorbanceReaderFixture } from './AbsorbanceReaderFixture' +import { FlexStackerFixture } from './FlexStackerFixture' import type { ReactNode } from 'react' import type { @@ -31,11 +39,6 @@ import type { CutoutId, DeckConfiguration, } from '@opentrons/shared-data' -import { TemperatureModuleFixture } from './TemperatureModuleFixture' -import { HeaterShakerFixture } from './HeaterShakerFixture' -import { MagneticBlockFixture } from './MagneticBlockFixture' -import { ThermocyclerFixture } from './ThermocyclerFixture' -import { AbsorbanceReaderFixture } from './AbsorbanceReaderFixture' export * from './constants' @@ -116,6 +119,9 @@ export function DeckConfigurator(props: DeckConfiguratorProps): JSX.Element { ({ cutoutFixtureId }) => cutoutFixtureId === STAGING_AREA_SLOT_WITH_MAGNETIC_BLOCK_V1_FIXTURE ) + const flexStackerFixtures = deckConfig.filter(({ cutoutFixtureId }) => + FLEX_STACKER_FIXTURES.includes(cutoutFixtureId) + ) return ( ))} + {flexStackerFixtures.map(({ cutoutId, cutoutFixtureId }) => ( + + ))} {additionalStaticFixtures?.map(staticFixture => ( Date: Wed, 29 Jan 2025 15:57:21 -0500 Subject: [PATCH 20/22] fix(shared-data): add D3 as provided addressable area to the flexStackerModuleV1WithWasteChuteRightAdapterCovered fixture. (#17376) - add a short-term fix for the addressable chute+stacker fixture to enable ABR and testing. --- shared-data/deck/definitions/5/ot3_standard.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/shared-data/deck/definitions/5/ot3_standard.json b/shared-data/deck/definitions/5/ot3_standard.json index fda49c38f2d..f317b596ad1 100644 --- a/shared-data/deck/definitions/5/ot3_standard.json +++ b/shared-data/deck/definitions/5/ot3_standard.json @@ -1026,7 +1026,8 @@ "cutoutD3": [ "1ChannelWasteChute", "8ChannelWasteChute", - "flexStackerModuleV1D4" + "flexStackerModuleV1D4", + "D3" ] }, "fixtureGroup": {}, @@ -1043,7 +1044,8 @@ "8ChannelWasteChute", "96ChannelWasteChute", "gripperWasteChute", - "flexStackerModuleV1D4" + "flexStackerModuleV1D4", + "D3" ] }, "fixtureGroup": {}, From 2451026c9f9aca43115309c8168c81d1be429ee7 Mon Sep 17 00:00:00 2001 From: Joe Wojak Date: Wed, 29 Jan 2025 16:21:37 -0500 Subject: [PATCH 21/22] docs(api): Update listed pipette flow rates (#17367) # Overview The API docs section on [default pipette flow rates](https://docs.opentrons.com/v2/pipettes/characteristics.html#pipette-flow-rates) shows inaccurate flow rates. The parent page/file is `characteristics.rst`. This updates that table based on the flow rate data provided in these 2 JIRA issues: - RTC-667 - RESC-375 Both include a list of default flow rates. Excluding 20 uL tips because those are not available yet. ## Test Plan and Hands on Testing Check the updated table to make sure it reflects the correct default flow rates. ## Changelog Change updates and revised the table that lists flow rates for various pipette and tip combinations. Minor text changes in section text. ## Review requests See RTC-667 for a list of flow rates. I think I've got these reproduced correctly. ## Risk assessment Low. Docs change only. Minor table and text change in a single section. --- api/docs/v2/pipettes/characteristics.rst | 49 +++++++++++++----------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/api/docs/v2/pipettes/characteristics.rst b/api/docs/v2/pipettes/characteristics.rst index 9203dd81816..00971d71832 100644 --- a/api/docs/v2/pipettes/characteristics.rst +++ b/api/docs/v2/pipettes/characteristics.rst @@ -184,29 +184,32 @@ These flow rates will remain in effect until you change the ``flow_rate`` attrib Flex Pipette Flow Rates ----------------------- -Flex pipette flow rates depend on pipette volume and tip capacity. Each pipette–tip combination has a default flow rate for aspirating, dispensing, and blowing out liquid. When using a 50 µL pipette, you should only use 50 µL tips. - -.. list-table:: - :header-rows: 1 - - * - Pipette Model - - Tip Capacity (µL) - - Flow Rate (µL/s) - * - 50 µL (1- and 8-channel) - - 50 - - 57 - * - 1000 µL (1-, 8-, and 96-channel) - - 50 - - 478 - * - 1000 µL (1-, 8-, and 96-channel) - - 200 - - 716 - * - 1000 µL (1-, 8-, and 96-channel) - - 1000 - - 716 - - -Additionally, all Flex pipettes have a well bottom clearance of 1 mm for aspirate and dispense actions. +The following table provides data on the default aspirate, dispense, and blowout flow rates (in µL/s) for Flex pipettes. Default flow rates for each pipette-tip combination are the same across all three actions. + +.. Excludes low-vol 96 channel. Not yet released. + ++-----------------------------+-------------------+------------------------+ +| Pipette Model | Tip Capacity (µL) | Default Flow Rate (µL) | ++=============================+===================+========================+ +| 1- and 8-channel (50 µL) | 50 | 35 | ++-----------------------------+-------------------+------------------------+ +| 1- and 8-channel (1000 µL) | 50 | 478 | ++ +-------------------+------------------------+ +| | 200 | 716 | ++ +-------------------+------------------------+ +| | 1000 | 716 | ++-----------------------------+-------------------+------------------------+ +| 96-channel (5-1000 µL) | 50 | 6 | ++ +-------------------+------------------------+ +| | 200 | 80 | ++ +-------------------+------------------------+ +| | 1000 | 160 | ++-----------------------------+-------------------+------------------------+ + +Additionally: + +- When using a 50 µL pipette, you should only use 50 µL tips. +- All Flex pipettes have a well bottom clearance of 1 mm for aspirate and dispense actions. .. _ot2-flow-rates: From ac70ce08b43d0601604d7c6817fdf3915fb305b9 Mon Sep 17 00:00:00 2001 From: Brayan Almonte Date: Thu, 30 Jan 2025 10:44:29 -0500 Subject: [PATCH 22/22] fix(api): tune store_labware motion parameters and current to increase the z torque. (#17382) Motion parameters need to be adjusted to account for tiprack weight by decreasing the speed when moving on the z-axis when storing labware. This pull request decreases the z speed to half the move speed and also decreases the current back down to 1.5mAmps since the lower speeds increase the torque. --- api/src/opentrons/drivers/flex_stacker/driver.py | 4 ++-- .../hardware_control/modules/flex_stacker.py | 13 +++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/api/src/opentrons/drivers/flex_stacker/driver.py b/api/src/opentrons/drivers/flex_stacker/driver.py index 270cd759f90..e96a3a96095 100644 --- a/api/src/opentrons/drivers/flex_stacker/driver.py +++ b/api/src/opentrons/drivers/flex_stacker/driver.py @@ -67,14 +67,14 @@ max_speed=10.0, acceleration=100.0, max_speed_discont=40, - current=1.8, + current=1.5, ), "move": MoveParams( StackerAxis.Z, max_speed=200.0, acceleration=500.0, max_speed_discont=40, - current=1.8, + current=1.5, ), }, StackerAxis.L: { diff --git a/api/src/opentrons/hardware_control/modules/flex_stacker.py b/api/src/opentrons/hardware_control/modules/flex_stacker.py index 136ac1d18bc..3c12673a1a5 100644 --- a/api/src/opentrons/hardware_control/modules/flex_stacker.py +++ b/api/src/opentrons/hardware_control/modules/flex_stacker.py @@ -273,7 +273,9 @@ async def move_axis( await self.reset_stall_detected() motion_params = STACKER_MOTION_CONFIG[axis]["move"] await self._driver.set_run_current(axis, current or motion_params.current or 0) - if any([speed, acceleration]): + if any([speed, acceleration, current]): + motion_params = self._reader.motion_params[axis] + motion_params.current = current or motion_params.current motion_params.max_speed = speed or motion_params.max_speed motion_params.acceleration = acceleration or motion_params.acceleration distance = direction.distance(distance) @@ -391,8 +393,11 @@ async def store_labware(self, labware_height: float) -> bool: # Transfer await self.open_latch() - await self.move_axis(StackerAxis.Z, Direction.EXTEND, (labware_height / 2)) - await self.home_axis(StackerAxis.Z, Direction.EXTEND) + z_speed = (STACKER_MOTION_CONFIG[StackerAxis.Z]["move"].max_speed or 0) / 2 + await self.move_axis( + StackerAxis.Z, Direction.EXTEND, (labware_height / 2), z_speed + ) + await self.home_axis(StackerAxis.Z, Direction.EXTEND, z_speed) await self.close_latch() # Move Z then X axis @@ -448,7 +453,7 @@ async def get_limit_switch_status(self) -> None: async def get_motion_parameters(self) -> None: """Get the motion parameters used by the axis motors.""" - self.move_params = { + self.motion_params = { axis: await self._driver.get_motion_params(axis) for axis in StackerAxis }

    L18-ETDv!5MxKD_S^^XG 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