From c3d66786d3af2fb73ee9f13c9a9efd50d4245ecc Mon Sep 17 00:00:00 2001 From: Jethary Rader <66035149+jerader@users.noreply.github.com> Date: Mon, 6 May 2024 14:01:52 -0400 Subject: [PATCH] refactor(protocol-designer, step-generation): multi tiprack uses defURI instead of id (#15096) closes AUTH-12 --- .../protocol/8/doItAllV3MigratedToV8.json | 4 +-- .../protocol/8/doItAllV4MigratedToV8.json | 2 +- .../protocol/8/doItAllV7MigratedToV8.json | 4 +-- .../fixtures/protocol/8/doItAllV8.json | 2 +- .../protocol/8/example_1_1_0MigratedToV8.json | 4 +-- .../fixtures/protocol/8/mix_8_0_0.json | 2 +- .../8/newAdvancedSettingsAndMultiTemp.json | 2 +- .../8/ninetySixChannelFullAndColumn.json | 4 +-- .../StepEditForm/fields/TiprackField.tsx | 10 +++--- .../fields/__tests__/TiprackField.test.tsx | 6 ++-- .../src/load-file/migration/8_1_0.ts | 11 ++++--- .../test/createPresavedStepForm.test.ts | 4 +-- .../utils/createPresavedStepForm.ts | 12 ++----- .../steplist/test/generateSubsteps.test.ts | 6 ++-- .../generateRobotStateTimeline.test.ts | 11 +++++-- protocol-designer/src/ui/labware/selectors.ts | 18 ++++------- .../src/__tests__/consolidate.test.ts | 11 +++++-- .../src/__tests__/distribute.test.ts | 7 ++-- .../getIsSafePipetteMovement.test.ts | 13 ++++---- step-generation/src/__tests__/mix.test.ts | 9 ++++-- .../src/__tests__/replaceTip.test.ts | 32 ++++++++++++------- .../src/__tests__/robotStateSelectors.test.ts | 28 ++++++++-------- .../src/__tests__/transfer.test.ts | 5 ++- step-generation/src/robotStateSelectors.ts | 9 ++---- .../src/utils/safePipetteMovements.ts | 9 +++--- 25 files changed, 121 insertions(+), 104 deletions(-) diff --git a/protocol-designer/fixtures/protocol/8/doItAllV3MigratedToV8.json b/protocol-designer/fixtures/protocol/8/doItAllV3MigratedToV8.json index 9407020457b..c33b1764d40 100644 --- a/protocol-designer/fixtures/protocol/8/doItAllV3MigratedToV8.json +++ b/protocol-designer/fixtures/protocol/8/doItAllV3MigratedToV8.json @@ -73,7 +73,7 @@ "3961e4c0-75c7-11ea-b42f-4b64e50f43e5": { "pipette": "0b3f2210-75c7-11ea-b42f-4b64e50f43e5", "volume": "40", - "tipRack": "0b44c760-75c7-11ea-b42f-4b64e50f43e5:opentrons/opentrons_96_tiprack_300ul/1", + "tipRack": "opentrons/opentrons_96_tiprack_300ul/1", "changeTip": "always", "path": "multiDispense", "aspirate_wells_grouped": false, @@ -175,7 +175,7 @@ "mix_touchTip_mmFromBottom": 11.8, "dropTip_location": "8053a205-f2dc-4b1d-8d05-bf8233949e2e:trashBin", "nozzles": null, - "tipRack": "0b44c760-75c7-11ea-b42f-4b64e50f43e5:opentrons/opentrons_96_tiprack_300ul/1", + "tipRack": "opentrons/opentrons_96_tiprack_300ul/1", "mix_x_position": 0, "mix_y_position": 0, "blowout_z_offset": 0, diff --git a/protocol-designer/fixtures/protocol/8/doItAllV4MigratedToV8.json b/protocol-designer/fixtures/protocol/8/doItAllV4MigratedToV8.json index 15e2e2203dd..5876d7bf450 100644 --- a/protocol-designer/fixtures/protocol/8/doItAllV4MigratedToV8.json +++ b/protocol-designer/fixtures/protocol/8/doItAllV4MigratedToV8.json @@ -107,7 +107,7 @@ "3961e4c0-75c7-11ea-b42f-4b64e50f43e5": { "pipette": "0b3f2210-75c7-11ea-b42f-4b64e50f43e5", "volume": "30", - "tipRack": "0b44c760-75c7-11ea-b42f-4b64e50f43e5:opentrons/opentrons_96_tiprack_300ul/1", + "tipRack": "opentrons/opentrons_96_tiprack_300ul/1", "changeTip": "always", "path": "single", "aspirate_wells_grouped": false, diff --git a/protocol-designer/fixtures/protocol/8/doItAllV7MigratedToV8.json b/protocol-designer/fixtures/protocol/8/doItAllV7MigratedToV8.json index b9981a7badd..47fe0d1f860 100644 --- a/protocol-designer/fixtures/protocol/8/doItAllV7MigratedToV8.json +++ b/protocol-designer/fixtures/protocol/8/doItAllV7MigratedToV8.json @@ -151,7 +151,7 @@ "f9a294f1-f42b-4cae-893a-592405349d56": { "pipette": "2e7c6344-58ab-465c-b542-489883cb63fe", "volume": "100", - "tipRack": "23ed35de-5bfd-4bb0-8f54-da99a2804ed9:opentrons/opentrons_flex_96_filtertiprack_50ul/1", + "tipRack": "opentrons/opentrons_flex_96_filtertiprack_50ul/1", "changeTip": "always", "path": "single", "aspirate_wells_grouped": false, @@ -227,7 +227,7 @@ "mix_touchTip_mmFromBottom": null, "dropTip_location": "134504e1-b212-41cf-966d-2560deb5b693:trashBin", "nozzles": null, - "tipRack": "23ed35de-5bfd-4bb0-8f54-da99a2804ed9:opentrons/opentrons_flex_96_filtertiprack_50ul/1", + "tipRack": "opentrons/opentrons_flex_96_filtertiprack_50ul/1", "mix_x_position": 0, "mix_y_position": 0, "blowout_z_offset": 0, diff --git a/protocol-designer/fixtures/protocol/8/doItAllV8.json b/protocol-designer/fixtures/protocol/8/doItAllV8.json index 2d4953ee801..61f1e788852 100644 --- a/protocol-designer/fixtures/protocol/8/doItAllV8.json +++ b/protocol-designer/fixtures/protocol/8/doItAllV8.json @@ -111,7 +111,7 @@ "d2f74144-a7bf-4ba2-aaab-30d70b2b62c7": { "pipette": "9fcd50d9-92b2-45ac-acf1-e2cf773feffc", "volume": "100", - "tipRack": "f2d371ea-5146-4c89-8200-9c056a7f321a:opentrons/opentrons_flex_96_tiprack_1000ul/1", + "tipRack": "opentrons/opentrons_flex_96_tiprack_1000ul/1", "changeTip": "always", "path": "single", "aspirate_wells_grouped": false, diff --git a/protocol-designer/fixtures/protocol/8/example_1_1_0MigratedToV8.json b/protocol-designer/fixtures/protocol/8/example_1_1_0MigratedToV8.json index efb8deaad57..c789d62cacc 100644 --- a/protocol-designer/fixtures/protocol/8/example_1_1_0MigratedToV8.json +++ b/protocol-designer/fixtures/protocol/8/example_1_1_0MigratedToV8.json @@ -75,7 +75,7 @@ "e7d36200-92a5-11e9-ac62-1b173f839d9e": { "pipette": "c6f45030-92a5-11e9-ac62-1b173f839d9e", "volume": "6", - "tipRack": "c6f4ec70-92a5-11e9-ac62-1b173f839d9e:tiprack-10ul", + "tipRack": "opentrons/opentrons_96_tiprack_10ul/1", "changeTip": "always", "path": "single", "aspirate_wells_grouped": false, @@ -161,7 +161,7 @@ "mix_touchTip_mmFromBottom": 30.5, "dropTip_location": "9b1c0d01-9d4f-4016-afe6-9e08b46acf5e:trashBin", "nozzles": null, - "tipRack": "c6f4ec70-92a5-11e9-ac62-1b173f839d9e:tiprack-10ul", + "tipRack": "opentrons/opentrons_96_tiprack_10ul/1", "mix_x_position": 0, "mix_y_position": 0, "blowout_z_offset": 0, diff --git a/protocol-designer/fixtures/protocol/8/mix_8_0_0.json b/protocol-designer/fixtures/protocol/8/mix_8_0_0.json index 766dcbc177e..6684720c7d9 100644 --- a/protocol-designer/fixtures/protocol/8/mix_8_0_0.json +++ b/protocol-designer/fixtures/protocol/8/mix_8_0_0.json @@ -74,7 +74,7 @@ "mix_touchTip_mmFromBottom": null, "dropTip_location": "5ba7047d-d3e2-4845-9eaa-1974af796ead:trashBin", "nozzles": null, - "tipRack": "f1c677c0-fc3a-11ea-8809-e959e7d61d96:opentrons/opentrons_96_tiprack_10ul/1", + "tipRack": "opentrons/opentrons_96_tiprack_10ul/1", "mix_x_position": 0, "mix_y_position": 0, "blowout_z_offset": 0, diff --git a/protocol-designer/fixtures/protocol/8/newAdvancedSettingsAndMultiTemp.json b/protocol-designer/fixtures/protocol/8/newAdvancedSettingsAndMultiTemp.json index ebcb9862d7b..58325488533 100644 --- a/protocol-designer/fixtures/protocol/8/newAdvancedSettingsAndMultiTemp.json +++ b/protocol-designer/fixtures/protocol/8/newAdvancedSettingsAndMultiTemp.json @@ -55,7 +55,7 @@ "stepDetails": "", "pipette": "21087f15-4c03-4587-8a2b-1ba0b5a501a0", "volume": "10", - "tipRack": "0d39213c-49c2-4170-bf19-4c09e1b72aca:opentrons/opentrons_flex_96_tiprack_50ul/1", + "tipRack": "opentrons/opentrons_flex_96_tiprack_50ul/1", "changeTip": "always", "path": "single", "aspirate_wells_grouped": false, diff --git a/protocol-designer/fixtures/protocol/8/ninetySixChannelFullAndColumn.json b/protocol-designer/fixtures/protocol/8/ninetySixChannelFullAndColumn.json index b642d0cb564..dc58d3219a2 100644 --- a/protocol-designer/fixtures/protocol/8/ninetySixChannelFullAndColumn.json +++ b/protocol-designer/fixtures/protocol/8/ninetySixChannelFullAndColumn.json @@ -50,7 +50,7 @@ "83a095fa-b649-4105-99d4-177f1a3f363a": { "pipette": "de7da440-95ec-43e8-8723-851321fbd6f9", "volume": "10", - "tipRack": "75aa666f-98d8-4af9-908e-963ced428580:opentrons/opentrons_flex_96_tiprack_50ul/1", + "tipRack": "opentrons/opentrons_flex_96_tiprack_50ul/1", "changeTip": "always", "path": "single", "aspirate_wells_grouped": false, @@ -107,7 +107,7 @@ "f5ea3139-1585-4848-9d5f-832eb88c99ca": { "pipette": "de7da440-95ec-43e8-8723-851321fbd6f9", "volume": "10", - "tipRack": "75aa666f-98d8-4af9-908e-963ced428580:opentrons/opentrons_flex_96_tiprack_50ul/1", + "tipRack": "opentrons/opentrons_flex_96_tiprack_50ul/1", "changeTip": "always", "path": "single", "aspirate_wells_grouped": false, diff --git a/protocol-designer/src/components/StepEditForm/fields/TiprackField.tsx b/protocol-designer/src/components/StepEditForm/fields/TiprackField.tsx index 464b15b4f7f..7c9f2cea2a0 100644 --- a/protocol-designer/src/components/StepEditForm/fields/TiprackField.tsx +++ b/protocol-designer/src/components/StepEditForm/fields/TiprackField.tsx @@ -30,13 +30,13 @@ export function TiprackField(props: TiprackFieldProps): JSX.Element { const [targetProps, tooltipProps] = useHoverTooltip() const pipetteEntities = useSelector(getPipetteEntities) const options = useSelector(uiLabwareSelectors.getTiprackOptions) - const defaultTipracks = + const defaultTiprackUris = pipetteId != null ? pipetteEntities[pipetteId as string].tiprackDefURI : [] - const pipetteOptions = options.filter(option => - defaultTipracks.includes(option.defURI) + const tiprackOptions = options.filter(option => + defaultTiprackUris.includes(option.value) ) - const hasMissingTiprack = defaultTipracks.length > pipetteOptions.length + const hasMissingTiprack = defaultTiprackUris.length > tiprackOptions.length return ( { }) vi.mocked(getTiprackOptions).mockReturnValue([ { - value: 'mockValue', + value: 'mockDefURI1', name: 'tiprack1', - defURI: 'mockDefURI1', }, { - value: 'mockValue', + value: 'mockDefURI2', name: 'tiprack2', - defURI: 'mockDefURI2', }, ]) }) diff --git a/protocol-designer/src/load-file/migration/8_1_0.ts b/protocol-designer/src/load-file/migration/8_1_0.ts index 8c268252867..1733316120d 100644 --- a/protocol-designer/src/load-file/migration/8_1_0.ts +++ b/protocol-designer/src/load-file/migration/8_1_0.ts @@ -46,6 +46,9 @@ export const migrateFile = ( {} ) + const pipetteTiprackAssignments = + designerApplication.data?.pipetteTiprackAssignments + const loadLabwareCommands = commands.filter( (command): command is LoadLabwareCreateCommand => command.commandType === 'loadLabware' @@ -74,9 +77,6 @@ export const migrateFile = ( const tiprackLoadCommands = loadLabwareCommands.filter( command => command.params.loadName === tiprackLoadName ) - const tiprackIds = tiprackLoadCommands.map( - command => command.params.labwareId - ) const xyKeys = item.stepType === 'mix' ? { mix_x_position: 0, mix_y_position: 0 } @@ -105,6 +105,7 @@ export const migrateFile = ( const pipetteName = loadPipetteCommands.find( pipette => pipette.params.pipetteId === item.pipette )?.params.pipetteName + const defaultBlowOutFlowRate = getDefaultBlowoutFlowRate( pipetteName as PipetteName, item.volume, @@ -116,11 +117,13 @@ export const migrateFile = ( blowoutFlowRate = null } + const tipRackDefURI = pipetteTiprackAssignments[item.pipette] + acc[item.id] = { ...item, blowout_flowRate: blowoutFlowRate, blowout_z_offset: 0, - tipRack: tiprackIds[0], + tipRack: tipRackDefURI, ...xyKeys, } return acc diff --git a/protocol-designer/src/step-forms/test/createPresavedStepForm.test.ts b/protocol-designer/src/step-forms/test/createPresavedStepForm.test.ts index f7e37d2e467..326cb5ab742 100644 --- a/protocol-designer/src/step-forms/test/createPresavedStepForm.test.ts +++ b/protocol-designer/src/step-forms/test/createPresavedStepForm.test.ts @@ -141,7 +141,7 @@ describe('createPresavedStepForm', () => { pipette: 'leftPipetteId', nozzles: null, stepType: 'moveLiquid', - tipRack: null, + tipRack: 'defaultTipRack', // default fields dropTip_location: 'mockTrash', aspirate_airGap_checkbox: false, @@ -228,7 +228,7 @@ describe('createPresavedStepForm', () => { volume: undefined, aspirate_flowRate: null, dispense_flowRate: null, - tipRack: null, + tipRack: 'defaultTipRack', blowout_flowRate: null, }) }) diff --git a/protocol-designer/src/step-forms/utils/createPresavedStepForm.ts b/protocol-designer/src/step-forms/utils/createPresavedStepForm.ts index 1ebfca8bf0c..5e3563683b0 100644 --- a/protocol-designer/src/step-forms/utils/createPresavedStepForm.ts +++ b/protocol-designer/src/step-forms/utils/createPresavedStepForm.ts @@ -132,11 +132,6 @@ const _patchDefaultTiprack = (args: { savedStepForms, orderedStepIds, } = args - const labware = initialDeckSetup.labware - const tipRackIds = Object.values(labware) - .filter(lw => lw.def.parameters.isTiprack) - .map(lw => lw.id) - const defaultPipetteId = getNextDefaultPipetteId( savedStepForms, orderedStepIds, @@ -145,15 +140,12 @@ const _patchDefaultTiprack = (args: { const pipetteFirstTiprackDefUri = pipetteEntities[defaultPipetteId].tiprackDefURI[0] - const defaultTiprackId = tipRackIds.find(id => - id.includes(pipetteFirstTiprackDefUri) - ) const formHasTipRackField = formData && 'tipRack' in formData - if (formHasTipRackField && defaultTiprackId != null) { + if (formHasTipRackField) { const updatedFields = handleFormChange( { - tipRack: defaultTiprackId, + tipRack: pipetteFirstTiprackDefUri, }, formData, pipetteEntities, diff --git a/protocol-designer/src/steplist/test/generateSubsteps.test.ts b/protocol-designer/src/steplist/test/generateSubsteps.test.ts index 6e70c18cacf..194e3303442 100644 --- a/protocol-designer/src/steplist/test/generateSubsteps.test.ts +++ b/protocol-designer/src/steplist/test/generateSubsteps.test.ts @@ -4,9 +4,11 @@ import { makeContext, FIXED_TRASH_ID, } from '@opentrons/step-generation' +import { fixtureTiprack300ul, getLabwareDefURI } from '@opentrons/shared-data' import { THERMOCYCLER_STATE } from '../../constants' import { generateSubstepItem } from '../generateSubstepItem' +import type { LabwareDefinition2 } from '@opentrons/shared-data' import type { RobotState, InvariantContext, @@ -181,7 +183,7 @@ describe('generateSubstepItem', () => { dispenseFlowRateUlSec: 5, dispenseOffsetFromBottomMm: 10, dropTipLocation: FIXED_TRASH_ID, - tipRack: 'tiprack1Id', + tipRack: getLabwareDefURI(fixtureTiprack300ul as LabwareDefinition2), } }) ;[ @@ -404,7 +406,7 @@ describe('generateSubstepItem', () => { aspirateFlowRateUlSec: 5, dispenseFlowRateUlSec: 5, dropTipLocation: FIXED_TRASH_ID, - tipRack: 'tiprack1Id', + tipRack: getLabwareDefURI(fixtureTiprack300ul as LabwareDefinition2), }, // @ts-expect-error(sa, 2021-6-15): errors should be boolean typed errors: {}, diff --git a/protocol-designer/src/timelineMiddleware/__tests__/generateRobotStateTimeline.test.ts b/protocol-designer/src/timelineMiddleware/__tests__/generateRobotStateTimeline.test.ts index 1717dc838cb..795512828dc 100644 --- a/protocol-designer/src/timelineMiddleware/__tests__/generateRobotStateTimeline.test.ts +++ b/protocol-designer/src/timelineMiddleware/__tests__/generateRobotStateTimeline.test.ts @@ -10,6 +10,11 @@ import { } from '@opentrons/step-generation' import { generateRobotStateTimeline } from '../generateRobotStateTimeline' import type { StepArgsAndErrorsById } from '../../steplist' +import { + LabwareDefinition2, + fixtureTiprack300ul, + getLabwareDefURI, +} from '@opentrons/shared-data' vi.mock('../../labware-defs/utils') @@ -49,7 +54,7 @@ describe('generateRobotStateTimeline', () => { mixBeforeAspirate: null, description: null, nozzles: null, - tipRack: 'tiprack1Id', + tipRack: getLabwareDefURI(fixtureTiprack300ul as LabwareDefinition2), aspirateXOffset: 0, aspirateYOffset: 0, dispenseXOffset: 0, @@ -89,7 +94,7 @@ describe('generateRobotStateTimeline', () => { mixBeforeAspirate: null, description: null, nozzles: null, - tipRack: 'tiprack1Id', + tipRack: getLabwareDefURI(fixtureTiprack300ul as LabwareDefinition2), aspirateXOffset: 0, aspirateYOffset: 0, dispenseXOffset: 0, @@ -121,7 +126,7 @@ describe('generateRobotStateTimeline', () => { aspirateDelaySeconds: null, dispenseDelaySeconds: null, nozzles: null, - tipRack: 'tiprack1Id', + tipRack: getLabwareDefURI(fixtureTiprack300ul as LabwareDefinition2), aspirateXOffset: 0, aspirateYOffset: 0, dispenseXOffset: 0, diff --git a/protocol-designer/src/ui/labware/selectors.ts b/protocol-designer/src/ui/labware/selectors.ts index 27b3ea9f3ae..669d265a427 100644 --- a/protocol-designer/src/ui/labware/selectors.ts +++ b/protocol-designer/src/ui/labware/selectors.ts @@ -241,27 +241,22 @@ export const getDisposalOptions = createSelector( } ) -export interface TiprackOption { - name: string - value: string - defURI: string -} -export const getTiprackOptions: Selector = createSelector( +export const getTiprackOptions: Selector = createSelector( stepFormSelectors.getLabwareEntities, getLabwareNicknamesById, (labwareEntities, nicknamesById) => { const options = reduce( labwareEntities, ( - acc: TiprackOption[], + acc: DropdownOption[], labwareEntity: LabwareEntity, labwareId: string - ): TiprackOption[] => { + ): DropdownOption[] => { const labwareDefURI = labwareEntity.labwareDefURI - const optionValues = acc.map(option => option.value) + const optionDefURI = acc.map(option => option.value) if ( - optionValues.includes(labwareDefURI) || + optionDefURI.includes(labwareDefURI) || !getIsTiprack(labwareEntity.def) ) { return acc @@ -270,8 +265,7 @@ export const getTiprackOptions: Selector = createSelector( ...acc, { name: nicknamesById[labwareId], - value: labwareId, - defURI: labwareDefURI, + value: labwareDefURI, }, ] } diff --git a/step-generation/src/__tests__/consolidate.test.ts b/step-generation/src/__tests__/consolidate.test.ts index 11b20e65267..9733fe5caa6 100644 --- a/step-generation/src/__tests__/consolidate.test.ts +++ b/step-generation/src/__tests__/consolidate.test.ts @@ -1,4 +1,5 @@ import { beforeEach, describe, it, expect } from 'vitest' +import { getLabwareDefURI, fixtureTiprack300ul } from '@opentrons/shared-data' import { consolidate } from '../commandCreators/compound/consolidate' import { FIXED_TRASH_ID } from '../constants' import { @@ -25,7 +26,11 @@ import { blowoutInPlaceHelper, } from '../fixtures' import { DEST_WELL_BLOWOUT_DESTINATION } from '../utils' -import type { AspDispAirgapParams, CreateCommand } from '@opentrons/shared-data' +import type { + AspDispAirgapParams, + CreateCommand, + LabwareDefinition2, +} from '@opentrons/shared-data' import type { ConsolidateArgs, InvariantContext, RobotState } from '../types' const airGapHelper = makeAirGapHelper({ @@ -99,7 +104,7 @@ beforeEach(() => { mixInDestination: null, blowoutLocation: null, dropTipLocation: FIXED_TRASH_ID, - tipRack: 'tiprack1Id', + tipRack: getLabwareDefURI(fixtureTiprack300ul as LabwareDefinition2), aspirateXOffset: 0, dispenseXOffset: 0, aspirateYOffset: 0, @@ -3210,7 +3215,7 @@ describe('consolidate multi-channel', () => { const data: ConsolidateArgs = { ...args, volume: 140, - tipRack: 'tiprack1Id', + tipRack: getLabwareDefURI(fixtureTiprack300ul as LabwareDefinition2), changeTip: 'once', aspirateXOffset: 0, dispenseXOffset: 0, diff --git a/step-generation/src/__tests__/distribute.test.ts b/step-generation/src/__tests__/distribute.test.ts index 6793b9df81e..a2bd499d1fc 100644 --- a/step-generation/src/__tests__/distribute.test.ts +++ b/step-generation/src/__tests__/distribute.test.ts @@ -1,5 +1,6 @@ import { beforeEach, describe, it, expect } from 'vitest' import { FIXED_TRASH_ID } from '../constants' +import { fixtureTiprack300ul, getLabwareDefURI } from '@opentrons/shared-data' import { ASPIRATE_OFFSET_FROM_BOTTOM_MM, blowoutHelper, @@ -24,7 +25,7 @@ import { blowoutInPlaceHelper, } from '../fixtures' import { distribute } from '../commandCreators/compound/distribute' -import type { CreateCommand } from '@opentrons/shared-data' +import type { CreateCommand, LabwareDefinition2 } from '@opentrons/shared-data' import type { DistributeArgs, InvariantContext, RobotState } from '../types' import { SOURCE_WELL_BLOWOUT_DESTINATION, @@ -73,7 +74,7 @@ beforeEach(() => { commandCreatorFnName: 'distribute', name: 'distribute test', description: 'test blah blah', - tipRack: 'tiprack1Id', + tipRack: getLabwareDefURI(fixtureTiprack300ul as LabwareDefinition2), pipette: DEFAULT_PIPETTE, sourceLabware: SOURCE_LABWARE, destLabware: DEST_LABWARE, @@ -254,7 +255,7 @@ describe('tip handling for multiple distribute chunks', () => { destWells: ['A2', 'A3', 'A4', 'A5'], changeTip: 'always', volume: 150, - tipRack: 'tiprack1Id', + tipRack: getLabwareDefURI(fixtureTiprack300ul as LabwareDefinition2), } as DistributeArgs const result = distribute( diff --git a/step-generation/src/__tests__/getIsSafePipetteMovement.test.ts b/step-generation/src/__tests__/getIsSafePipetteMovement.test.ts index b0d40489178..b3ff5cba24d 100644 --- a/step-generation/src/__tests__/getIsSafePipetteMovement.test.ts +++ b/step-generation/src/__tests__/getIsSafePipetteMovement.test.ts @@ -14,6 +14,7 @@ import { InvariantContext, RobotState } from '../types' const mockLabwareId = 'labwareId' const mockPipId = 'pip' const mockTiprackId = 'tiprackId' +const mockTipUri = 'mockTipUri' const mockModule = 'moduleId' const mockLabware2 = 'labwareId2' const mockAdapter = 'adapterId' @@ -35,7 +36,7 @@ const mockInvariantProperties: InvariantContext = { }, [mockTiprackId]: { id: mockTiprackId, - labwareDefURI: 'mockTipUri', + labwareDefURI: mockTipUri, def: fixtureTiprack1000ul as LabwareDefinition2, }, [mockAdapter]: { @@ -84,7 +85,7 @@ describe('getIsSafePipetteMovement', () => { }, 'mockId', 'mockTrashBin', - 'mockTiprackId', + mockTipUri, { x: 0, y: 0, z: 0 } ) expect(result).toEqual(true) @@ -95,7 +96,7 @@ describe('getIsSafePipetteMovement', () => { mockInvariantProperties, mockPipId, mockLabwareId, - mockTiprackId, + mockTipUri, { x: -12, y: -100, z: 20 } ) expect(result).toEqual(false) @@ -116,7 +117,7 @@ describe('getIsSafePipetteMovement', () => { mockInvariantProperties, mockPipId, mockLabwareId, - mockTiprackId, + mockTipUri, { x: -1, y: 5, z: 20 } ) expect(result).toEqual(true) @@ -128,7 +129,7 @@ describe('getIsSafePipetteMovement', () => { mockInvariantProperties, mockPipId, mockLabwareId, - mockTiprackId, + mockTipUri, { x: -1, y: 5, z: 0 } ) expect(result).toEqual(false) @@ -158,7 +159,7 @@ describe('getIsSafePipetteMovement', () => { mockInvariantProperties, mockPipId, mockLabwareId, - mockTiprackId, + mockTipUri, { x: 0, y: 0, z: 0 } ) expect(result).toEqual(false) diff --git a/step-generation/src/__tests__/mix.test.ts b/step-generation/src/__tests__/mix.test.ts index 9fd099a5388..9f39d8722b7 100644 --- a/step-generation/src/__tests__/mix.test.ts +++ b/step-generation/src/__tests__/mix.test.ts @@ -1,6 +1,10 @@ import { beforeEach, describe, it, expect } from 'vitest' import flatMap from 'lodash/flatMap' -import { FIXED_TRASH_ID } from '@opentrons/shared-data' +import { + FIXED_TRASH_ID, + fixtureTiprack300ul, + getLabwareDefURI, +} from '@opentrons/shared-data' import { mix } from '../commandCreators/compound/mix' import { getRobotStateWithTipStandard, @@ -18,6 +22,7 @@ import { makeTouchTipHelper, delayCommand, } from '../fixtures' +import type { LabwareDefinition2 } from '@opentrons/shared-data' import type { ChangeTipOptions, InvariantContext, @@ -41,7 +46,7 @@ beforeEach(() => { commandCreatorFnName: 'mix', name: 'mix test', description: 'test blah blah', - tipRack: 'tiprack1Id', + tipRack: getLabwareDefURI(fixtureTiprack300ul as LabwareDefinition2), pipette: DEFAULT_PIPETTE, labware: SOURCE_LABWARE, diff --git a/step-generation/src/__tests__/replaceTip.test.ts b/step-generation/src/__tests__/replaceTip.test.ts index 0cd85058ca4..01a88101f6b 100644 --- a/step-generation/src/__tests__/replaceTip.test.ts +++ b/step-generation/src/__tests__/replaceTip.test.ts @@ -1,6 +1,11 @@ import { beforeEach, describe, it, expect } from 'vitest' import merge from 'lodash/merge' -import { COLUMN } from '@opentrons/shared-data' +import { + COLUMN, + fixtureTiprack1000ul, + fixtureTiprack300ul, + getLabwareDefURI, +} from '@opentrons/shared-data' import { getInitialRobotStateStandard, makeContext, @@ -13,14 +18,17 @@ import { moveToAddressableAreaHelper, DEFAULT_PIPETTE, } from '../fixtures' -import { FIXED_TRASH_ID } from '..' import { replaceTip } from '../commandCreators/atomic/replaceTip' +import { FIXED_TRASH_ID } from '../constants' +import type { LabwareDefinition2 } from '@opentrons/shared-data' import type { InvariantContext, RobotState } from '../types' const tiprack1Id = 'tiprack1Id' const tiprack2Id = 'tiprack2Id' const tiprack4Id = 'tiprack4Id' const tiprack5Id = 'tiprack5Id' +const tiprackURI1 = getLabwareDefURI(fixtureTiprack300ul as LabwareDefinition2) +const tiprackURI2 = getLabwareDefURI(fixtureTiprack1000ul as LabwareDefinition2) const p300SingleId = DEFAULT_PIPETTE const p300MultiId = 'p300MultiId' const p100096Id = 'p100096Id' @@ -38,7 +46,7 @@ describe('replaceTip', () => { { pipette: p300SingleId, dropTipLocation: FIXED_TRASH_ID, - tipRack: tiprack1Id, + tipRack: tiprackURI1, }, invariantContext, initialRobotState @@ -51,7 +59,7 @@ describe('replaceTip', () => { { pipette: p300SingleId, dropTipLocation: FIXED_TRASH_ID, - tipRack: tiprack1Id, + tipRack: tiprackURI1, }, invariantContext, merge({}, initialRobotState, { @@ -85,7 +93,7 @@ describe('replaceTip', () => { { pipette: p300SingleId, dropTipLocation: FIXED_TRASH_ID, - tipRack: tiprack1Id, + tipRack: tiprackURI1, }, invariantContext, initialTestRobotState @@ -110,7 +118,7 @@ describe('replaceTip', () => { { pipette: p300SingleId, dropTipLocation: FIXED_TRASH_ID, - tipRack: tiprack1Id, + tipRack: tiprackURI1, }, invariantContext, initialTestRobotState @@ -136,7 +144,7 @@ describe('replaceTip', () => { { pipette: p300SingleId, dropTipLocation: FIXED_TRASH_ID, - tipRack: tiprack1Id, + tipRack: tiprackURI1, }, invariantContext, initialTestRobotState @@ -175,7 +183,7 @@ describe('replaceTip', () => { { pipette: p300SingleId, dropTipLocation: 'wasteChuteId', - tipRack: tiprack1Id, + tipRack: tiprackURI1, }, invariantContext, initialTestRobotState @@ -194,7 +202,7 @@ describe('replaceTip', () => { { pipette: p300MultiId, dropTipLocation: FIXED_TRASH_ID, - tipRack: tiprack1Id, + tipRack: tiprackURI1, }, invariantContext, initialRobotState @@ -221,7 +229,7 @@ describe('replaceTip', () => { { pipette: p300MultiId, dropTipLocation: FIXED_TRASH_ID, - tipRack: tiprack1Id, + tipRack: tiprackURI1, }, invariantContext, robotStateWithTipA1Missing @@ -247,7 +255,7 @@ describe('replaceTip', () => { { pipette: p300MultiId, dropTipLocation: FIXED_TRASH_ID, - tipRack: tiprack1Id, + tipRack: tiprackURI1, }, invariantContext, robotStateWithTipsOnMulti @@ -292,7 +300,7 @@ describe('replaceTip', () => { { pipette: p100096Id, dropTipLocation: 'wasteChuteId', - tipRack: tiprack5Id, + tipRack: tiprackURI2, nozzles: COLUMN, }, invariantContext, diff --git a/step-generation/src/__tests__/robotStateSelectors.test.ts b/step-generation/src/__tests__/robotStateSelectors.test.ts index e74549a87ed..637ddaa22da 100644 --- a/step-generation/src/__tests__/robotStateSelectors.test.ts +++ b/step-generation/src/__tests__/robotStateSelectors.test.ts @@ -22,7 +22,9 @@ import { InvariantContext } from '../types' let invariantContext: InvariantContext const fixtureTiprack300ul = _fixtureTiprack300ul as LabwareDefinition2 -const mockTiprackId = 'tiprack1Id' +const mockTiprackURI = getLabwareDefURI( + fixtureTiprack300ul as LabwareDefinition2 +) beforeEach(() => { invariantContext = makeContext() @@ -153,7 +155,7 @@ describe('getNextTiprack - single-channel', () => { const result = getNextTiprack( DEFAULT_PIPETTE, - mockTiprackId, + mockTiprackURI, invariantContext, robotState ) @@ -172,7 +174,7 @@ describe('getNextTiprack - single-channel', () => { const result = getNextTiprack( DEFAULT_PIPETTE, - mockTiprackId, + mockTiprackURI, invariantContext, robotState ) @@ -191,7 +193,7 @@ describe('getNextTiprack - single-channel', () => { }) const result = getNextTiprack( DEFAULT_PIPETTE, - mockTiprackId, + mockTiprackURI, invariantContext, robotState ) @@ -215,7 +217,7 @@ describe('getNextTiprack - single-channel', () => { robotState.tipState.tipracks.tiprack2Id.A1 = false const result = getNextTiprack( DEFAULT_PIPETTE, - mockTiprackId, + mockTiprackURI, invariantContext, robotState ) @@ -236,7 +238,7 @@ describe('getNextTiprack - single-channel', () => { }) const result = getNextTiprack( DEFAULT_PIPETTE, - mockTiprackId, + mockTiprackURI, invariantContext, robotState ) @@ -258,7 +260,7 @@ describe('getNextTiprack - 8-channel', () => { const result = getNextTiprack( 'p300MultiId', - mockTiprackId, + mockTiprackURI, invariantContext, robotState ) @@ -284,7 +286,7 @@ describe('getNextTiprack - 8-channel', () => { } const result = getNextTiprack( 'p300MultiId', - mockTiprackId, + mockTiprackURI, invariantContext, robotState ) @@ -304,7 +306,7 @@ describe('getNextTiprack - 8-channel', () => { }) const result = getNextTiprack( 'p300MultiId', - mockTiprackId, + mockTiprackURI, invariantContext, robotState ) @@ -339,7 +341,7 @@ describe('getNextTiprack - 8-channel', () => { const result = getNextTiprack( 'p300MultiId', - mockTiprackId, + mockTiprackURI, invariantContext, robotState ) @@ -360,7 +362,7 @@ describe('getNextTiprack - 8-channel', () => { }) const result = getNextTiprack( 'p300MultiId', - mockTiprackId, + mockTiprackURI, invariantContext, robotState ) @@ -420,7 +422,7 @@ describe('getNextTiprack - 8-channel', () => { const result = getNextTiprack( 'p300MultiId', - mockTiprackId, + mockTiprackURI, invariantContext, robotState ) @@ -446,7 +448,7 @@ describe('getNextTiprack - 8-channel', () => { }) const result = getNextTiprack( 'p300MultiId', - mockTiprackId, + mockTiprackURI, invariantContext, robotState ) diff --git a/step-generation/src/__tests__/transfer.test.ts b/step-generation/src/__tests__/transfer.test.ts index b3da39db41d..72c89fc264a 100644 --- a/step-generation/src/__tests__/transfer.test.ts +++ b/step-generation/src/__tests__/transfer.test.ts @@ -1,6 +1,8 @@ import { beforeEach, describe, it, expect, test } from 'vitest' import { ONE_CHANNEL_WASTE_CHUTE_ADDRESSABLE_AREA, + fixtureTiprack300ul, + getLabwareDefURI, WASTE_CHUTE_CUTOUT, } from '@opentrons/shared-data' import { @@ -31,6 +33,7 @@ import { SOURCE_WELL_BLOWOUT_DESTINATION, } from '../utils/misc' import { transfer } from '../commandCreators/compound/transfer' +import type { LabwareDefinition2 } from '@opentrons/shared-data' import type { InvariantContext, RobotState, TransferArgs } from '../types' const airGapHelper = makeAirGapHelper({ @@ -68,7 +71,7 @@ beforeEach(() => { name: 'Transfer Test', description: 'test blah blah', pipette: DEFAULT_PIPETTE, - tipRack: 'tiprack1Id', + tipRack: getLabwareDefURI(fixtureTiprack300ul as LabwareDefinition2), sourceLabware: SOURCE_LABWARE, destLabware: DEST_LABWARE, diff --git a/step-generation/src/robotStateSelectors.ts b/step-generation/src/robotStateSelectors.ts index 6f0e17bfef1..4b1b0e9310e 100644 --- a/step-generation/src/robotStateSelectors.ts +++ b/step-generation/src/robotStateSelectors.ts @@ -91,7 +91,7 @@ interface NextTiprackInfo { } export function getNextTiprack( pipetteId: string, - tipRack: string, + tipRackUri: string, invariantContext: InvariantContext, robotState: RobotState, nozzles?: NozzleConfigurationStyle @@ -119,9 +119,7 @@ export function getNextTiprack( const isOnDeck = robotState.labware[labwareId].slot != null const labwareIdDefUri = invariantContext.labwareEntities[labwareId].labwareDefURI - const tipRackDefUri = - invariantContext.labwareEntities[tipRack].labwareDefURI - return isOnDeck && labwareIdDefUri === tipRackDefUri + return isOnDeck && labwareIdDefUri === tipRackUri } ) const is96Channel = pipetteEntity.spec.channels === 96 @@ -186,14 +184,13 @@ export function getNextTiprack( export function getPipetteWithTipMaxVol( pipetteId: string, invariantContext: InvariantContext, - tipRack: string + tipRackDefUri: string ): number { // NOTE: this fn assumes each pipette is assigned to exactly one tiprack type, // across the entire timeline const pipetteEntity = invariantContext.pipetteEntities[pipetteId] const pipetteMaxVol = pipetteEntity.spec.liquids.default.maxVolume const tiprackDef = pipetteEntity.tiprackLabwareDef - const tipRackDefUri = invariantContext.labwareEntities[tipRack].labwareDefURI let chosenTipRack = null for (const def of tiprackDef) { if (getLabwareDefURI(def) === tipRackDefUri) { diff --git a/step-generation/src/utils/safePipetteMovements.ts b/step-generation/src/utils/safePipetteMovements.ts index ea1d7d0cadc..8fa82fa585f 100644 --- a/step-generation/src/utils/safePipetteMovements.ts +++ b/step-generation/src/utils/safePipetteMovements.ts @@ -301,7 +301,7 @@ export const getIsSafePipetteMovement = ( invariantContext: InvariantContext, pipetteId: string, labwareId: string, - tipRackId: string, + tipRackDefURI: string, wellLocationOffset: Point ): boolean => { const deckDefinition = getDeckDefFromRobotType(FLEX_ROBOT_TYPE) @@ -317,15 +317,16 @@ export const getIsSafePipetteMovement = ( if (labwareEntities[labwareId] == null) { return true } + const tiprackTipLength = Object.values(labwareEntities).find( + labwareEntity => labwareEntity.labwareDefURI === tipRackDefURI + )?.def.parameters.tipLength const stagingAreaSlots = Object.values(additionalEquipmentEntities) .filter(ae => ae.name === 'stagingArea') .map(stagingArea => stagingArea.location as string) const pipetteEntity = pipetteEntities[pipetteId] const pipetteHasTip = tipState.pipettes[pipetteId] - const tipLength = pipetteHasTip - ? labwareEntities[tipRackId].def.parameters.tipLength ?? 0 - : 0 + const tipLength = pipetteHasTip ? tiprackTipLength ?? 0 : 0 const wellLocationPoint = getWellPosition( labwareEntities[labwareId], wellLocationOffset