From 9f5a9e1623468ae800d1286c070c6ce3926bc9c0 Mon Sep 17 00:00:00 2001 From: Jethary Rader <66035149+jerader@users.noreply.github.com> Date: Tue, 28 May 2024 12:23:28 -0400 Subject: [PATCH] fix(step-generation): properly emit configureNozzleLayout command (#15269) closes RQA-2781 --- .../src/__tests__/replaceTip.test.ts | 44 +++++++++++++++++++ .../src/commandCreators/atomic/replaceTip.ts | 20 ++++++++- .../commandCreators/compound/consolidate.ts | 14 ------ .../commandCreators/compound/distribute.ts | 14 ------ .../src/commandCreators/compound/mix.ts | 13 ------ .../src/commandCreators/compound/transfer.ts | 13 ------ 6 files changed, 63 insertions(+), 55 deletions(-) diff --git a/step-generation/src/__tests__/replaceTip.test.ts b/step-generation/src/__tests__/replaceTip.test.ts index 01a88101f6b..f814ca8a04b 100644 --- a/step-generation/src/__tests__/replaceTip.test.ts +++ b/step-generation/src/__tests__/replaceTip.test.ts @@ -17,6 +17,7 @@ import { dropTipInPlaceHelper, moveToAddressableAreaHelper, DEFAULT_PIPETTE, + PIPETTE_96, } from '../fixtures' import { replaceTip } from '../commandCreators/atomic/replaceTip' import { FIXED_TRASH_ID } from '../constants' @@ -129,6 +130,49 @@ describe('replaceTip', () => { pickUpTipHelper('B1'), ]) }) + it('96-channel full tip and emits the configure nozzle layout command before picking up tip', () => { + const initialTestRobotState = merge({}, initialRobotState, { + tipState: { + tipracks: { + [tiprack1Id]: { + A1: false, + }, + }, + pipettes: { + [PIPETTE_96]: true, + }, + }, + pipettes: { + [PIPETTE_96]: { nozzles: 'ALL' }, + }, + }) + const result = replaceTip( + { + pipette: PIPETTE_96, + dropTipLocation: FIXED_TRASH_ID, + tipRack: tiprackURI1, + nozzles: COLUMN, + }, + invariantContext, + initialTestRobotState + ) + const res = getSuccessResult(result) + expect(res.commands).toEqual([ + ...dropTipHelper(PIPETTE_96), + { + commandType: 'configureNozzleLayout', + key: expect.any(String), + params: { + pipetteId: PIPETTE_96, + configurationParams: { + primaryNozzle: 'A12', + style: COLUMN, + }, + }, + }, + pickUpTipHelper('A2', { pipetteId: PIPETTE_96 }), + ]) + }) it('Single-channel: used all tips in first rack, move to second rack', () => { const initialTestRobotState = merge({}, initialRobotState, { tipState: { diff --git a/step-generation/src/commandCreators/atomic/replaceTip.ts b/step-generation/src/commandCreators/atomic/replaceTip.ts index 77e112d75a6..1ec43834964 100644 --- a/step-generation/src/commandCreators/atomic/replaceTip.ts +++ b/step-generation/src/commandCreators/atomic/replaceTip.ts @@ -22,6 +22,7 @@ import { getWasteChuteAddressableAreaNamePip, } from '../../utils' import { dropTip } from './dropTip' +import { configureNozzleLayout } from './configureNozzleLayout' import type { NozzleConfigurationStyle } from '@opentrons/shared-data' import type { @@ -29,6 +30,7 @@ import type { CommandCreatorError, CurriedCommandCreator, } from '../../types' + interface PickUpTipArgs { pipette: string tiprack: string @@ -91,7 +93,7 @@ export const replaceTip: CommandCreator = ( prevRobotState ) => { const { pipette, dropTipLocation, nozzles, tipRack } = args - + const stateNozzles = prevRobotState.pipettes[pipette].nozzles if (tipRack == null) { return { errors: [errorCreators.noTipSelected()], @@ -106,6 +108,7 @@ export const replaceTip: CommandCreator = ( ) const pipetteSpec = invariantContext.pipetteEntities[pipette]?.spec const channels = pipetteSpec?.channels + const hasMoreTipracksOnDeck = tipracks?.totalTipracks > tipracks?.filteredTipracks @@ -241,11 +244,24 @@ export const replaceTip: CommandCreator = ( const addressableAreaNameWasteChute = getWasteChuteAddressableAreaNamePip( channels ) + + const configureNozzleLayoutCommand: CurriedCommandCreator[] = + // only emit the command if previous nozzle state is different + channels === 96 && args.nozzles != null && args.nozzles !== stateNozzles + ? [ + curryCommandCreator(configureNozzleLayout, { + nozzles: args.nozzles, + pipetteId: args.pipette, + }), + ] + : [] + let commandCreators: CurriedCommandCreator[] = [ curryCommandCreator(dropTip, { pipette, dropTipLocation, }), + ...configureNozzleLayoutCommand, curryCommandCreator(_pickUpTip, { pipette, tiprack: nextTiprack.tiprackId, @@ -260,6 +276,7 @@ export const replaceTip: CommandCreator = ( addressableAreaName: addressableAreaNameWasteChute, prevRobotState, }), + ...configureNozzleLayoutCommand, curryCommandCreator(_pickUpTip, { pipette, tiprack: nextTiprack.tiprackId, @@ -275,6 +292,7 @@ export const replaceTip: CommandCreator = ( prevRobotState, invariantContext, }), + ...configureNozzleLayoutCommand, curryCommandCreator(_pickUpTip, { pipette, tiprack: nextTiprack.tiprackId, diff --git a/step-generation/src/commandCreators/compound/consolidate.ts b/step-generation/src/commandCreators/compound/consolidate.ts index f7fc4c85f9d..abe2392c7c1 100644 --- a/step-generation/src/commandCreators/compound/consolidate.ts +++ b/step-generation/src/commandCreators/compound/consolidate.ts @@ -24,7 +24,6 @@ import { import { aspirate, configureForVolume, - configureNozzleLayout, delay, dropTip, moveToWell, @@ -486,20 +485,7 @@ export const consolidate: CommandCreator = ( const dropTipAfterDispenseAirGap = airGapAfterDispenseCommands.length > 0 ? dropTipCommand : [] - const stateNozzles = prevRobotState.pipettes[args.pipette].nozzles - const configureNozzleLayoutCommand: CurriedCommandCreator[] = - // only emit the command if previous nozzle state is different - is96Channel && args.nozzles != null && args.nozzles !== stateNozzles - ? [ - curryCommandCreator(configureNozzleLayout, { - nozzles: args.nozzles, - pipetteId: args.pipette, - }), - ] - : [] - return [ - ...configureNozzleLayoutCommand, ...tipCommands, ...configureForVolumeCommand, ...mixBeforeCommands, diff --git a/step-generation/src/commandCreators/compound/distribute.ts b/step-generation/src/commandCreators/compound/distribute.ts index eae11c1452f..853b43a768f 100644 --- a/step-generation/src/commandCreators/compound/distribute.ts +++ b/step-generation/src/commandCreators/compound/distribute.ts @@ -22,7 +22,6 @@ import { import { aspirate, configureForVolume, - configureNozzleLayout, delay, dispense, dropTip, @@ -460,20 +459,7 @@ export const distribute: CommandCreator = ( ] : [] - const stateNozzles = prevRobotState.pipettes[args.pipette].nozzles - const configureNozzleLayoutCommand: CurriedCommandCreator[] = - // only emit the command if previous nozzle state is different - is96Channel && args.nozzles != null && args.nozzles !== stateNozzles - ? [ - curryCommandCreator(configureNozzleLayout, { - nozzles: args.nozzles, - pipetteId: args.pipette, - }), - ] - : [] - return [ - ...configureNozzleLayoutCommand, ...tipCommands, ...configureForVolumeCommand, ...mixBeforeAspirateCommands, diff --git a/step-generation/src/commandCreators/compound/mix.ts b/step-generation/src/commandCreators/compound/mix.ts index 317613c1524..652036c2870 100644 --- a/step-generation/src/commandCreators/compound/mix.ts +++ b/step-generation/src/commandCreators/compound/mix.ts @@ -11,7 +11,6 @@ import * as errorCreators from '../../errorCreators' import { aspirate, configureForVolume, - configureNozzleLayout, delay, dispense, replaceTip, @@ -201,17 +200,6 @@ export const mix: CommandCreator = ( } } } - const stateNozzles = prevRobotState.pipettes[pipette].nozzles - const configureNozzleLayoutCommand: CurriedCommandCreator[] = - // only emit the command if previous nozzle state is different - is96Channel && data.nozzles != null && data.nozzles !== stateNozzles - ? [ - curryCommandCreator(configureNozzleLayout, { - nozzles: data.nozzles, - pipetteId: pipette, - }), - ] - : [] const configureForVolumeCommand: CurriedCommandCreator[] = LOW_VOLUME_PIPETTES.includes( invariantContext.pipetteEntities[pipette].name @@ -281,7 +269,6 @@ export const mix: CommandCreator = ( dispenseYOffset, }) return [ - ...configureNozzleLayoutCommand, ...tipCommands, ...configureForVolumeCommand, ...mixCommands, diff --git a/step-generation/src/commandCreators/compound/transfer.ts b/step-generation/src/commandCreators/compound/transfer.ts index 9c59d301aa4..156a73ba0f3 100644 --- a/step-generation/src/commandCreators/compound/transfer.ts +++ b/step-generation/src/commandCreators/compound/transfer.ts @@ -24,7 +24,6 @@ import { import { aspirate, configureForVolume, - configureNozzleLayout, delay, dispense, dropTip, @@ -274,17 +273,6 @@ export const transfer: CommandCreator = ( changeTipNow = isInitialSubtransfer || destinationWell !== prevDestWell } - const stateNozzles = prevRobotState.pipettes[args.pipette].nozzles - const configureNozzleLayoutCommand: CurriedCommandCreator[] = - // only emit the command if previous nozzle state is different - is96Channel && args.nozzles != null && args.nozzles !== stateNozzles - ? [ - curryCommandCreator(configureNozzleLayout, { - nozzles: args.nozzles, - pipetteId: args.pipette, - }), - ] - : [] const configureForVolumeCommand: CurriedCommandCreator[] = LOW_VOLUME_PIPETTES.includes( invariantContext.pipetteEntities[args.pipette].name @@ -603,7 +591,6 @@ export const transfer: CommandCreator = ( : [] const nextCommands = [ - ...configureNozzleLayoutCommand, ...tipCommands, ...preWetTipCommands, ...configureForVolumeCommand,