Skip to content

Commit 063368f

Browse files
authored
fix(protocol-designer): default the nozzle field value correctly (#18520)
closes RQA-4228
1 parent 4dd08e8 commit 063368f

File tree

4 files changed

+50
-110
lines changed

4 files changed

+50
-110
lines changed

protocol-designer/src/step-forms/utils/createPresavedStepForm.ts

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ const _patchDefaultPipette = (args: {
7474
orderedStepIds,
7575
initialDeckSetup.pipettes
7676
)
77+
const hasPartialTipSupportedChannel =
78+
pipetteEntities[defaultPipetteId]?.spec.channels !== 1
7779
// If there is a `pipette` field in the form,
7880
// then set `pipette` field of new steps to the next default pipette id.
7981
//
@@ -85,32 +87,7 @@ const _patchDefaultPipette = (args: {
8587
const updatedFields = handleFormChange(
8688
{
8789
pipette: defaultPipetteId,
88-
},
89-
formData,
90-
pipetteEntities,
91-
labwareEntities
92-
)
93-
return updatedFields
94-
}
95-
96-
return null
97-
}
98-
99-
const _patchDefaultNozzle = (args: {
100-
labwareEntities: LabwareEntities
101-
pipetteEntities: PipetteEntities
102-
}): FormUpdater => formData => {
103-
const { labwareEntities, pipetteEntities } = args
104-
const hasPartialTipSupportedChannel = Object.values(pipetteEntities).find(
105-
pip => pip.spec.channels === 96 || pip.spec.channels === 8
106-
)
107-
108-
const formHasNozzlesField = formData && 'nozzles' in formData
109-
110-
if (formHasNozzlesField && hasPartialTipSupportedChannel) {
111-
const updatedFields = handleFormChange(
112-
{
113-
nozzles: ALL,
90+
nozzles: hasPartialTipSupportedChannel ? ALL : null,
11491
},
11592
formData,
11693
pipetteEntities,
@@ -439,11 +416,6 @@ export const createPresavedStepForm = ({
439416
stepType,
440417
})
441418

442-
const updateDefaultNozzles = _patchDefaultNozzle({
443-
labwareEntities,
444-
pipetteEntities,
445-
})
446-
447419
const updateDefaultDropTip = _patchDefaultDropTipLocation({
448420
labwareEntities,
449421
pipetteEntities,
@@ -516,7 +488,6 @@ export const createPresavedStepForm = ({
516488
updateAbsorbanceReaderModuleId,
517489
updateDefaultLabwareLocations,
518490
updateMoveLabwareFields,
519-
updateDefaultNozzles,
520491
].reduce<FormData>(
521492
(acc, updater: FormUpdater) => {
522493
const updates = updater(acc)

protocol-designer/src/steplist/formLevel/handleFormChange/dependentFieldsUpdateMix.ts

Lines changed: 28 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import pick from 'lodash/pick'
22

3+
import { ALL, SINGLE } from '@opentrons/shared-data'
4+
35
import { getDefaultsForStepType } from '../getDefaultsForStepType'
46
import {
57
chainPatchUpdaters,
@@ -9,6 +11,7 @@ import {
911
getDefaultWells,
1012
} from './utils'
1113

14+
import type { NozzleConfigurationStyle } from '@opentrons/shared-data'
1215
import type {
1316
LabwareEntities,
1417
PipetteEntities,
@@ -56,39 +59,21 @@ const updatePatchOnPipetteChannelChange = (
5659
): FormPatch => {
5760
if (patch.pipette === undefined) return patch
5861
let update = {}
59-
const prevChannels = getChannels(rawForm.pipette as string, pipetteEntities)
60-
const nChannels =
62+
const previousChannels = getChannels(
63+
rawForm.pipette as string,
64+
pipetteEntities
65+
)
66+
const nextChannels =
6167
typeof patch.pipette === 'string'
62-
? getChannels(patch.pipette, pipetteEntities)
68+
? getChannels(patch.pipette as string, pipetteEntities)
6369
: null
70+
6471
const appliedPatch = { ...rawForm, ...patch }
65-
let previousChannels = prevChannels
66-
if (
67-
rawForm.stepType === 'moveLiquid' ||
68-
(rawForm.stepType === 'mix' && prevChannels === 96)
69-
) {
70-
if (rawForm.nozzles === 'full') {
71-
previousChannels = 96
72-
} else {
73-
previousChannels = 8
74-
}
75-
}
76-
let nextChannels = nChannels
77-
if (
78-
rawForm.stepType === 'moveLiquid' ||
79-
(rawForm.stepType === 'mix' && nChannels === 96)
80-
) {
81-
if (rawForm.nozzles === 'full') {
82-
nextChannels = 96
83-
} else {
84-
nextChannels = 8
85-
}
86-
}
8772

8873
const singleToMulti =
89-
previousChannels === 1 && (nextChannels === 8 || nextChannels === 96)
74+
previousChannels === 1 && nextChannels === 8 && patch.nozzles !== SINGLE
9075
const multiToSingle =
91-
(previousChannels === 8 || previousChannels === 96) && nextChannels === 1
76+
previousChannels === 8 && rawForm.nozzles !== SINGLE && nextChannels === 1
9277

9378
if (patch.pipette === null || singleToMulti) {
9479
// reset all well selection
@@ -102,17 +87,6 @@ const updatePatchOnPipetteChannelChange = (
10287
}),
10388
}
10489
} else if (multiToSingle) {
105-
let channels: 8 | 96 = 8
106-
if (
107-
rawForm.stepType === 'moveLiquid' ||
108-
(rawForm.stepType === 'mix' && prevChannels === 96)
109-
) {
110-
if (rawForm.nozzles === 'full') {
111-
channels = 96
112-
} else {
113-
channels = 8
114-
}
115-
}
11690
// multi-channel to single-channel: convert primary wells to all wells
11791
const labwareId = appliedPatch.labware
11892

@@ -122,7 +96,7 @@ const updatePatchOnPipetteChannelChange = (
12296
wells: getAllWellsFromPrimaryWells(
12397
appliedPatch.wells as string[],
12498
labwareDef,
125-
channels
99+
previousChannels
126100
),
127101
}
128102
}
@@ -133,19 +107,25 @@ const updatePatchOnPipetteChannelChange = (
133107

134108
const updatePatchOnPipetteChange = (
135109
patch: FormPatch,
136-
rawForm: FormData
110+
rawForm: FormData,
111+
pipetteEntities: PipetteEntities
137112
): FormPatch => {
138113
// when pipette ID is changed (to another ID, or to null),
139114
// set any flow rates to null
140115
if (fieldHasChanged(rawForm, patch, 'pipette')) {
116+
let nozzles: NozzleConfigurationStyle | null = null
117+
const newPipette = patch.pipette
118+
119+
if (typeof newPipette === 'string' && newPipette in pipetteEntities) {
120+
const hasPartialTipSupportedChannel =
121+
pipetteEntities[newPipette].spec.channels !== 1
122+
nozzles = hasPartialTipSupportedChannel ? ALL : null
123+
}
124+
141125
return {
142126
...patch,
143-
...getDefaultFields(
144-
'aspirate_flowRate',
145-
'dispense_flowRate',
146-
'tipRack',
147-
'nozzles'
148-
),
127+
...getDefaultFields('aspirate_flowRate', 'dispense_flowRate', 'tipRack'),
128+
nozzles,
149129
}
150130
}
151131

@@ -166,23 +146,6 @@ const updatePatchOnTiprackChange = (
166146
return patch
167147
}
168148

169-
const updatePatchOnNozzleChange = (
170-
patch: FormPatch,
171-
rawForm: FormData,
172-
pipetteEntities: PipetteEntities
173-
): FormPatch => {
174-
if (
175-
Object.values(pipetteEntities).find(pip => pip.spec.channels === 96) &&
176-
fieldHasChanged(rawForm, patch, 'nozzles')
177-
) {
178-
return {
179-
...patch,
180-
...getDefaultFields('wells'),
181-
}
182-
}
183-
return patch
184-
}
185-
186149
export function dependentFieldsUpdateMix(
187150
originalPatch: FormPatch,
188151
rawForm: FormData, // raw = NOT hydrated
@@ -205,9 +168,8 @@ export function dependentFieldsUpdateMix(
205168
labwareEntities,
206169
pipetteEntities
207170
),
208-
chainPatch => updatePatchOnPipetteChange(chainPatch, rawForm),
209-
chainPatch => updatePatchOnTiprackChange(chainPatch, rawForm),
210171
chainPatch =>
211-
updatePatchOnNozzleChange(chainPatch, rawForm, pipetteEntities),
172+
updatePatchOnPipetteChange(chainPatch, rawForm, pipetteEntities),
173+
chainPatch => updatePatchOnTiprackChange(chainPatch, rawForm),
212174
])
213175
}

protocol-designer/src/steplist/formLevel/handleFormChange/dependentFieldsUpdateMoveLiquid.ts

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import clamp from 'lodash/clamp'
22
import pick from 'lodash/pick'
33
import round from 'lodash/round'
44

5-
import { getPipetteSpecsV2 } from '@opentrons/shared-data'
5+
import { ALL, getPipetteSpecsV2, SINGLE } from '@opentrons/shared-data'
66
import {
77
DEST_WELL_BLOWOUT_DESTINATION,
88
SOURCE_WELL_BLOWOUT_DESTINATION,
@@ -26,6 +26,7 @@ import {
2626
volumeInCapacityForMulti,
2727
} from './utils'
2828

29+
import type { NozzleConfigurationStyle } from '@opentrons/shared-data'
2930
import type {
3031
LabwareEntities,
3132
PipetteEntities,
@@ -236,10 +237,14 @@ const updatePatchOnPipetteChange = (
236237
if (fieldHasChanged(rawForm, patch, 'pipette')) {
237238
const newPipette = patch.pipette
238239
let airGapVolume: string | null = null
240+
let nozzles: NozzleConfigurationStyle | null = null
239241

240242
if (typeof newPipette === 'string' && newPipette in pipetteEntities) {
241243
const minVolume = getMinPipetteVolume(pipetteEntities[newPipette])
242244
airGapVolume = minVolume.toString()
245+
const hasPartialTipSupportedChannel =
246+
pipetteEntities[newPipette].spec.channels !== 1
247+
nozzles = hasPartialTipSupportedChannel ? ALL : null
243248
}
244249

245250
return {
@@ -252,9 +257,9 @@ const updatePatchOnPipetteChange = (
252257
'disposalVolume_volume',
253258
'aspirate_mmFromBottom',
254259
'dispense_mmFromBottom',
255-
'nozzles',
256260
'tipRack'
257261
),
262+
nozzles,
258263
aspirate_airGap_volume: airGapVolume,
259264
dispense_airGap_volume: airGapVolume,
260265
}
@@ -501,22 +506,27 @@ const updatePatchOnPipetteChannelChange = (
501506
): FormPatch => {
502507
if (patch.pipette === undefined) return patch
503508
let update: FormPatch = {}
504-
const prevChannels = getChannels(rawForm.pipette as string, pipetteEntities)
509+
const previousChannels = getChannels(
510+
rawForm.pipette as string,
511+
pipetteEntities
512+
)
505513
const nextChannels =
506514
typeof patch.pipette === 'string'
507515
? getChannels(patch.pipette, pipetteEntities)
508516
: null
517+
509518
const { id, stepType, ...stepData } = rawForm
510519
const appliedPatch: FormPatch = {
511520
...(stepData as FormPatch),
512521
...patch,
513522
id,
514523
stepType,
515524
}
525+
516526
const singleToMulti =
517-
prevChannels === 1 && (nextChannels === 8 || nextChannels === 96)
527+
previousChannels === 1 && nextChannels === 8 && patch.nozzles !== SINGLE
518528
const multiToSingle =
519-
(prevChannels === 8 || prevChannels === 96) && nextChannels === 1
529+
previousChannels === 8 && rawForm.nozzles !== SINGLE && nextChannels === 1
520530

521531
const pipetteId: string = appliedPatch.pipette as string
522532

@@ -539,10 +549,6 @@ const updatePatchOnPipetteChannelChange = (
539549
}),
540550
}
541551
} else if (multiToSingle) {
542-
let channels = 8
543-
if (prevChannels === 96) {
544-
channels = 96
545-
}
546552
// multi-channel to single-channel: convert primary wells to all wells
547553
const sourceLabwareId: string = appliedPatch.aspirate_labware as string
548554
const destLabwareId: string = appliedPatch.dispense_labware as string
@@ -554,7 +560,7 @@ const updatePatchOnPipetteChannelChange = (
554560
aspirate_wells: getAllWellsFromPrimaryWells(
555561
appliedPatch.aspirate_wells as string[],
556562
sourceLabware.def,
557-
channels as 8 | 96
563+
previousChannels
558564
),
559565
dispense_wells:
560566
destLabwareId.includes('trashBin') ||
@@ -568,7 +574,7 @@ const updatePatchOnPipetteChannelChange = (
568574
: getAllWellsFromPrimaryWells(
569575
appliedPatch.dispense_wells as string[],
570576
destLabware.def,
571-
channels as 8 | 96
577+
previousChannels
572578
),
573579
}
574580
}

protocol-designer/src/steplist/formLevel/handleFormChange/test/mix.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { beforeEach, describe, expect, it } from 'vitest'
22

3+
import { ALL } from '@opentrons/shared-data'
34
import {
45
fixture_96_plate,
56
fixture_tiprack_10_ul,
@@ -110,7 +111,7 @@ describe('well selection should update', () => {
110111
wells: [],
111112
aspirate_flowRate: null,
112113
dispense_flowRate: null,
113-
nozzles: null,
114+
nozzles: ALL,
114115
tipRack: null,
115116
})
116117
})

0 commit comments

Comments
 (0)