Skip to content

Commit c6ca409

Browse files
authored
feat(app): add command text in run log for loading liquid class (#17695)
1 parent dc7d164 commit c6ca409

File tree

10 files changed

+248
-3
lines changed

10 files changed

+248
-3
lines changed

app/src/assets/localization/en/protocol_command_text.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,15 @@
3333
"dropping_tip_in_trash": "Dropping tip in {{trash}}",
3434
"engaging_magnetic_module": "Engaging Magnetic Module",
3535
"fixed_trash": "Fixed Trash",
36+
"get_next_tip": "Calculating position of the next available tip",
3637
"home_gantry": "Homing all gantry, pipette, and plunger axes",
3738
"in_location": "in {{location}}",
3839
"latching_hs_latch": "Latching labware on Heater-Shaker",
3940
"left": "Left",
4041
"load_labware_to_display_location": "Load {{labware}} {{display_location}}",
4142
"load_lid": "Loading lid",
4243
"load_lid_stack": "Loading lid stack",
44+
"load_liquid_class": "Loading {{liquidClassDisplayName}} Liquid Class",
4345
"load_liquids_info_protocol_setup": "Load {{liquid}} into {{labware}}",
4446
"load_module_protocol_setup": "Load {{module}} in Slot {{slot_name}}",
4547
"load_pipette_protocol_setup": "Load {{pipette_name}} in {{mount_name}} Mount",

components/src/assets/localization/en/protocol_command_text.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,13 @@
3333
"dropping_tip_in_trash": "Dropping tip in {{trash}}",
3434
"engaging_magnetic_module": "Engaging Magnetic Module",
3535
"fixed_trash": "Fixed Trash",
36+
"get_next_tip": "Calculating position of the next available tip",
3637
"home_gantry": "Homing all gantry, pipette, and plunger axes",
3738
"in_location": "in {{location}}",
3839
"latching_hs_latch": "Latching labware on Heater-Shaker",
3940
"left": "Left",
4041
"load_labware_to_display_location": "Load {{labware}} {{display_location}}",
42+
"load_liquid_class": "Loading {{liquidClassDisplayName}} Liquid Class",
4143
"load_liquids_info_protocol_setup": "Load {{liquid}} into {{labware}}",
4244
"load_module_protocol_setup": "Load {{module}} in Slot {{slot_name}}",
4345
"load_pipette_protocol_setup": "Load {{pipette_name}} in {{mount_name}} Mount",

components/src/organisms/CommandText/__tests__/CommandText.test.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import type {
2828
PrepareToAspirateRunTimeCommand,
2929
RunTimeCommand,
3030
MoveToAddressableAreaForDropTipRunTimeCommand,
31+
LoadLiquidClassRunTimeCommand,
3132
} from '@opentrons/shared-data'
3233
import type { CommandTextData } from '../../ProtocolTimelineScrubber'
3334
import { getCommandTextData } from '../../ProtocolTimelineScrubber/utils'
@@ -693,6 +694,22 @@ describe('CommandText', () => {
693694
)
694695
screen.getByText('Load Water into fakeDisplayName')
695696
})
697+
it('renders correct text for loadLiquidClass', () => {
698+
renderWithProviders(
699+
<CommandText
700+
allRunDefs={[]}
701+
commandTextData={mockCommandTextData} // not relevant for loading liquid class
702+
robotType={FLEX_ROBOT_TYPE}
703+
command={
704+
mockRobotSideAnalysis.commands.find(
705+
c => c.commandType === 'loadLiquidClass'
706+
) as LoadLiquidClassRunTimeCommand
707+
}
708+
/>,
709+
{ i18nInstance: i18n }
710+
)
711+
screen.getByText('Loading Volatile Liquid Class')
712+
})
696713
it('renders correct text for temperatureModule/setTargetTemperature', () => {
697714
const mockTemp = 20
698715
renderWithProviders(

components/src/organisms/CommandText/fixtures/mockRobotSideAnalysis.json

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4747,6 +4747,154 @@
47474747
"startedAt": "2023-01-31T21:53:09.051665+00:00",
47484748
"completedAt": "2023-01-31T21:53:09.054733+00:00"
47494749
},
4750+
{
4751+
"id": "0ac7ca64-a8f8-4cf5-8640-96f43a9d51ac",
4752+
"createdAt": "2025-03-06T19:41:54.613414Z",
4753+
"commandType": "loadLiquidClass",
4754+
"key": "57373155b7cdb49d1828282c27b25aa7",
4755+
"status": "succeeded",
4756+
"params": {
4757+
"liquidClassRecord": {
4758+
"tiprack": "opentrons/opentrons_flex_96_tiprack_50ul/1",
4759+
"aspirate": {
4760+
"submerge": {
4761+
"positionReference": "well-top",
4762+
"offset": { "x": 0, "y": 0, "z": 2 },
4763+
"speed": 100,
4764+
"delay": { "enable": true, "params": { "duration": 0 } }
4765+
},
4766+
"retract": {
4767+
"positionReference": "well-top",
4768+
"offset": { "x": 0, "y": 0, "z": 2 },
4769+
"speed": 100,
4770+
"airGapByVolume": [
4771+
[1, 5],
4772+
[45, 5],
4773+
[50, 0]
4774+
],
4775+
"touchTip": {
4776+
"enable": false,
4777+
"params": { "zOffset": -1, "mmToEdge": 0.5, "speed": 30 }
4778+
},
4779+
"delay": { "enable": true, "params": { "duration": 0.5 } }
4780+
},
4781+
"positionReference": "well-top",
4782+
"offset": { "x": 0, "y": 0, "z": 2 },
4783+
"flowRateByVolume": [
4784+
[1, 7],
4785+
[10, 10],
4786+
[50, 30]
4787+
],
4788+
"correctionByVolume": [
4789+
[5, -2.1],
4790+
[10, -1.7],
4791+
[50, -3.3]
4792+
],
4793+
"preWet": false,
4794+
"mix": {
4795+
"enable": false,
4796+
"params": { "repetitions": 1, "volume": 50 }
4797+
},
4798+
"delay": { "enable": true, "params": { "duration": 0.2 } }
4799+
},
4800+
"singleDispense": {
4801+
"submerge": {
4802+
"positionReference": "well-top",
4803+
"offset": { "x": 0, "y": 0, "z": 2 },
4804+
"speed": 100,
4805+
"delay": { "enable": false, "params": { "duration": 0 } }
4806+
},
4807+
"retract": {
4808+
"positionReference": "well-top",
4809+
"offset": { "x": 0, "y": 0, "z": 2 },
4810+
"speed": 100,
4811+
"airGapByVolume": [
4812+
[1, 5],
4813+
[45, 5],
4814+
[50, 0]
4815+
],
4816+
"blowout": { "enable": false },
4817+
"touchTip": {
4818+
"enable": false,
4819+
"params": { "zOffset": -1, "mmToEdge": 0.5, "speed": 30 }
4820+
},
4821+
"delay": { "enable": true, "params": { "duration": 0.5 } }
4822+
},
4823+
"positionReference": "well-top",
4824+
"offset": { "x": 0, "y": 0, "z": 2 },
4825+
"flowRateByVolume": [[0, 125]],
4826+
"correctionByVolume": [
4827+
[5, -2.1],
4828+
[10, -1.7],
4829+
[50, -3.3]
4830+
],
4831+
"mix": {
4832+
"enable": false,
4833+
"params": { "repetitions": 1, "volume": 50 }
4834+
},
4835+
"pushOutByVolume": [
4836+
[5, 10],
4837+
[10, 5],
4838+
[45, 5],
4839+
[50, 0]
4840+
],
4841+
"delay": { "enable": true, "params": { "duration": 0.2 } }
4842+
},
4843+
"multiDispense": {
4844+
"submerge": {
4845+
"positionReference": "well-top",
4846+
"offset": { "x": 0, "y": 0, "z": 2 },
4847+
"speed": 100,
4848+
"delay": { "enable": false, "params": { "duration": 0 } }
4849+
},
4850+
"retract": {
4851+
"positionReference": "well-top",
4852+
"offset": { "x": 0, "y": 0, "z": 2 },
4853+
"speed": 100,
4854+
"airGapByVolume": [
4855+
[1, 5],
4856+
[45, 5],
4857+
[50, 0]
4858+
],
4859+
"blowout": { "enable": false },
4860+
"touchTip": {
4861+
"enable": false,
4862+
"params": { "zOffset": -1, "mmToEdge": 0.5, "speed": 30 }
4863+
},
4864+
"delay": { "enable": true, "params": { "duration": 0.5 } }
4865+
},
4866+
"positionReference": "well-top",
4867+
"offset": { "x": 0, "y": 0, "z": 2 },
4868+
"flowRateByVolume": [[0, 125]],
4869+
"correctionByVolume": [
4870+
[5, -2.1],
4871+
[10, -1.7],
4872+
[50, -3.3]
4873+
],
4874+
"conditioningByVolume": [
4875+
[1, 5],
4876+
[40, 5],
4877+
[45, 0],
4878+
[50, 0]
4879+
],
4880+
"disposalByVolume": [
4881+
[1, 5],
4882+
[40, 5],
4883+
[45, 0],
4884+
[50, 0]
4885+
],
4886+
"delay": { "enable": true, "params": { "duration": 0.2 } }
4887+
},
4888+
"liquidClassName": "ethanol_80",
4889+
"pipetteModel": "flex_1channel_1000"
4890+
}
4891+
},
4892+
"result": { "liquidClassId": "ee0cd074-2dba-4fe3-9bab-4ac5de494399" },
4893+
"startedAt": "2025-03-06T19:41:54.613492Z",
4894+
"completedAt": "2025-03-06T19:41:54.613826Z",
4895+
"notes": []
4896+
},
4897+
47504898
{
47514899
"id": "9c46d235-fe55-4e06-bacf-0f21a36d9c39",
47524900
"createdAt": "2023-01-31T21:53:09.120750+00:00",

components/src/organisms/CommandText/useCommandTextString/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ export function useCommandTextString(
108108
case 'loadPipette':
109109
case 'loadModule':
110110
case 'loadLiquid':
111+
case 'loadLiquidClass':
111112
return {
112113
kind: 'generic',
113114
commandText: utils.getLoadCommandText(fullParams),
@@ -230,6 +231,12 @@ export function useCommandTextString(
230231
}),
231232
}
232233

234+
case 'getNextTip':
235+
return {
236+
kind: 'generic',
237+
commandText: t('get_next_tip'),
238+
}
239+
233240
case 'moveToAddressableArea':
234241
return {
235242
kind: 'generic',

components/src/organisms/CommandText/useCommandTextString/utils/commandText/getLoadCommandText.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
import find from 'lodash/find'
12
import {
3+
getAllLiquidClassDefs,
24
getModuleDisplayName,
35
getModuleType,
46
getOccludedSlotCountForModule,
@@ -111,6 +113,16 @@ export const getLoadCommandText = ({
111113
: null,
112114
})
113115
}
116+
case 'loadLiquidClass': {
117+
const { liquidClassName } = command.params.liquidClassRecord
118+
const liquidClassDisplayName = find(
119+
getAllLiquidClassDefs(),
120+
liquidClassDef => liquidClassDef.liquidClassName === liquidClassName
121+
)?.displayName
122+
return t('load_liquid_class', {
123+
liquidClassDisplayName,
124+
})
125+
}
114126
default: {
115127
console.warn(
116128
'LoadCommandText encountered a command with an unrecognized commandType: ',

protocol-designer/src/assets/localization/en/protocol_command_text.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,13 @@
3333
"dropping_tip_in_trash": "Dropping tip in {{trash}}",
3434
"engaging_magnetic_module": "Engaging Magnetic Module",
3535
"fixed_trash": "Fixed Trash",
36+
"get_next_tip": "Calculating position of the next available tip",
3637
"home_gantry": "Homing all gantry, pipette, and plunger axes",
3738
"in_location": "in {{location}}",
3839
"latching_hs_latch": "Latching labware on Heater-Shaker",
3940
"left": "Left",
4041
"load_labware_to_display_location": "Load {{labware}} {{display_location}}",
42+
"load_liquid_class": "Loading {{liquidClassDisplayName}} Liquid Class",
4143
"load_liquids_info_protocol_setup": "Load {{liquid}} into {{labware}}",
4244
"load_module_protocol_setup": "Load {{module}} in Slot {{slot_name}}",
4345
"load_pipette_protocol_setup": "Load {{pipette_name}} in {{mount_name}} Mount",

shared-data/command/types/pipetting.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export type PipettingRunTimeCommand =
1313
| DropTipInPlaceRunTimeCommand
1414
| DropTipRunTimeCommand
1515
| GetTipPresenceRunTimeCommand
16+
| GetNextTipRunTimeCommand
1617
| MoveToAddressableAreaForDropTipRunTimeCommand
1718
| PickUpTipRunTimeCommand
1819
| PrepareToAspirateRunTimeCommand
@@ -36,6 +37,7 @@ export type PipettingCreateCommand =
3637
| DropTipCreateCommand
3738
| DropTipInPlaceCreateCommand
3839
| GetTipPresenceCreateCommand
40+
| GetNextTipCreateCommand
3941
| MoveToAddressableAreaForDropTipCreateCommand
4042
| PickUpTipCreateCommand
4143
| PrepareToAspirateCreateCommand
@@ -212,6 +214,16 @@ export interface GetTipPresenceRunTimeCommand
212214
result?: TipPresenceResult
213215
}
214216

217+
export interface GetNextTipCreateCommand extends CommonCommandCreateInfo {
218+
commandType: 'getNextTip'
219+
params: GetNextTipParams
220+
}
221+
export interface GetNextTipRunTimeCommand
222+
extends CommonCommandRunTimeInfo,
223+
GetNextTipCreateCommand {
224+
result?: GetNextTipResult
225+
}
226+
215227
export interface VerifyTipPresenceCreateCommand
216228
extends CommonCommandCreateInfo {
217229
commandType: 'verifyTipPresence'
@@ -286,6 +298,17 @@ export type TouchTipParams = PipetteAccessParams &
286298
speed?: number
287299
}
288300
export type DropTipParams = PipetteAccessParams & DropTipWellLocationParam
301+
export interface GetNextTipParams {
302+
pipetteId: string
303+
labwareIds: string[]
304+
}
305+
306+
export interface GetNextTipResult {
307+
nextTipInfo: {
308+
labwareId: string
309+
tipStartingWell: string
310+
}
311+
}
289312
export type PickUpTipParams = PipetteAccessParams & WellLocationParam
290313
export type PrepareToAspirateParams = PipetteIdentityParams
291314

shared-data/command/types/setup.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ import type {
66
LabwareOffset,
77
PipetteName,
88
ModuleModel,
9+
AspirateProperties,
10+
MultiDispenseProperties,
11+
SingleDispenseProperties,
912
} from '../../js'
1013

1114
export interface LoadPipetteCreateCommand extends CommonCommandCreateInfo {
@@ -87,6 +90,16 @@ export interface LoadLiquidRunTimeCommand
8790
result?: LoadLiquidResult
8891
}
8992

93+
export interface LoadLiquidClassCreateCommand extends CommonCommandCreateInfo {
94+
commandType: 'loadLiquidClass'
95+
params: LoadLiquidClassParams
96+
}
97+
export interface LoadLiquidClassRunTimeCommand
98+
extends CommonCommandRunTimeInfo,
99+
LoadLiquidClassCreateCommand {
100+
result?: LoadLiquidClassResult
101+
}
102+
90103
export interface ConfigureNozzleLayoutCreateCommand
91104
extends CommonCommandCreateInfo {
92105
commandType: 'configureNozzleLayout'
@@ -106,6 +119,7 @@ export type SetupRunTimeCommand =
106119
| ReloadLabwareRunTimeCommand
107120
| LoadModuleRunTimeCommand
108121
| LoadLiquidRunTimeCommand
122+
| LoadLiquidClassRunTimeCommand
109123
| MoveLabwareRunTimeCommand
110124
| LoadLidRunTimeCommand
111125
| LoadLidStackRunTimeCommand
@@ -117,6 +131,7 @@ export type SetupCreateCommand =
117131
| ReloadLabwareCreateCommand
118132
| LoadModuleCreateCommand
119133
| LoadLiquidCreateCommand
134+
| LoadLiquidClassCreateCommand
120135
| MoveLabwareCreateCommand
121136
| LoadLidCreateCommand
122137
| LoadLidStackCreateCommand
@@ -251,6 +266,23 @@ interface LoadLiquidParams {
251266
interface LoadLiquidResult {
252267
liquidId: string
253268
}
269+
interface LoadLiquidClassParams {
270+
liquidClassId?: string
271+
liquidClassRecord: LiquidClassRecord
272+
}
273+
274+
interface LiquidClassRecord {
275+
aspirate: AspirateProperties
276+
liquidClassName: string
277+
multiDispense?: MultiDispenseProperties
278+
pipetteModel: string
279+
singleDispense: SingleDispenseProperties
280+
tiprack: string
281+
}
282+
283+
interface LoadLiquidClassResult {
284+
liquidClassId: string
285+
}
254286

255287
export const COLUMN = 'COLUMN'
256288
export const SINGLE = 'SINGLE'

0 commit comments

Comments
 (0)