2
2
3
3
from __future__ import annotations
4
4
5
- from __future__ import annotations
6
5
from typing import Optional , Literal , TYPE_CHECKING
7
6
from typing_extensions import Type
8
7
9
8
from pydantic import BaseModel , Field
9
+ from pydantic .json_schema import SkipJsonSchema
10
10
11
11
from ..command import AbstractCommandImpl , BaseCommand , BaseCommandCreate , SuccessData
12
12
from ...errors import (
13
13
ErrorOccurrence ,
14
14
)
15
15
from ...errors .exceptions import FlexStackerLabwarePoolNotYetDefinedError
16
16
from ...state import update_types
17
- from ...types import StackerFillEmptyStrategy
18
- from opentrons .calibration_storage .helpers import uri_from_details
17
+ from ...types import (
18
+ StackerFillEmptyStrategy ,
19
+ StackerStoredLabwareGroup ,
20
+ NotOnDeckLocationSequenceComponent ,
21
+ OFF_DECK_LOCATION ,
22
+ InStackerHopperLocation ,
23
+ LabwareLocationSequence ,
24
+ OnLabwareLocation ,
25
+ LabwareLocation ,
26
+ )
27
+ from .common import (
28
+ labware_locations_for_group ,
29
+ primary_location_sequences ,
30
+ adapter_location_sequences_with_default ,
31
+ lid_location_sequences_with_default ,
32
+ )
33
+
19
34
20
35
if TYPE_CHECKING :
21
36
from ...state .state import StateView
@@ -66,14 +81,57 @@ class EmptyResult(BaseModel):
66
81
...,
67
82
description = "The labware definition URI of the primary labware." ,
68
83
)
69
- adapterLabwareURI : str | None = Field (
84
+ adapterLabwareURI : str | SkipJsonSchema [ None ] = Field (
70
85
None ,
71
86
description = "The labware definition URI of the adapter labware." ,
72
87
)
73
- lidLabwareURI : str | None = Field (
88
+ lidLabwareURI : str | SkipJsonSchema [ None ] = Field (
74
89
None ,
75
90
description = "The labware definition URI of the lid labware." ,
76
91
)
92
+ storedLabware : list [StackerStoredLabwareGroup ] | SkipJsonSchema [None ] = Field (
93
+ ..., description = "The primary labware loaded into the stacker labware pool."
94
+ )
95
+ removedLabware : list [StackerStoredLabwareGroup ] | SkipJsonSchema [None ] = Field (
96
+ ...,
97
+ description = "The labware objects that have just been removed from the stacker labware pool." ,
98
+ )
99
+ originalPrimaryLabwareLocationSequences : (
100
+ list [LabwareLocationSequence ] | SkipJsonSchema [None ]
101
+ ) = Field (
102
+ None ,
103
+ description = "The previous position of each newly-removed primary labware, in the same order as removedLabware." ,
104
+ )
105
+ originalAdapterLabwareLocationSequences : (
106
+ list [LabwareLocationSequence ] | SkipJsonSchema [None ]
107
+ ) = Field (
108
+ None ,
109
+ description = "The previous position of each newly-removed adapter labware, in the same order as removedLabware. None if the pool does not specify an adapter." ,
110
+ )
111
+ originalLidLabwareLocationSequences : (
112
+ list [LabwareLocationSequence ] | SkipJsonSchema [None ]
113
+ ) = Field (
114
+ None ,
115
+ description = "The previous position of each newly-removed lid labware, in the same order as removedLabware. None if the pool does not specify a lid." ,
116
+ )
117
+ newPrimaryLabwareLocationSequences : (
118
+ list [LabwareLocationSequence ] | SkipJsonSchema [None ]
119
+ ) = Field (
120
+ None ,
121
+ description = "The new position of each newly-removed primary labware, in the same order as removedLabware." ,
122
+ )
123
+ newAdapterLabwareLocationSequences : (
124
+ list [LabwareLocationSequence ] | SkipJsonSchema [None ]
125
+ ) = Field (
126
+ None ,
127
+ description = "The new position of each newly-removed adapter labware, in the same order as removedLabware. None if the pool does not specify an adapter." ,
128
+ )
129
+ newLidLabwareLocationSequences : (
130
+ list [LabwareLocationSequence ] | SkipJsonSchema [None ]
131
+ ) = Field (
132
+ None ,
133
+ description = "The new position of each newly-removed lid labware, in the same order as removedLabware. None if the pool does not specify a lid labware." ,
134
+ )
77
135
78
136
79
137
class EmptyImpl (AbstractCommandImpl [EmptyParams , SuccessData [EmptyResult ]]):
@@ -99,11 +157,42 @@ async def execute(self, params: EmptyParams) -> SuccessData[EmptyResult]:
99
157
100
158
count = params .count if params .count is not None else 0
101
159
102
- new_count = min (stacker_state .pool_count , count )
160
+ new_count = min (len (stacker_state .contained_labware_bottom_first ), count )
161
+
162
+ new_stored_labware = stacker_state .contained_labware_bottom_first [:new_count ]
163
+ removed_labware = stacker_state .contained_labware_bottom_first [new_count :]
164
+ new_locations_by_id : dict [str , LabwareLocation ] = {}
165
+ new_offset_ids_by_id : dict [str , str | None ] = {}
166
+
167
+ def _add_to_dicts (labware_group : StackerStoredLabwareGroup ) -> None :
168
+ if labware_group .adapterLabwareId :
169
+ new_locations_by_id [labware_group .primaryLabwareId ] = OnLabwareLocation (
170
+ labwareId = labware_group .adapterLabwareId
171
+ )
172
+ new_locations_by_id [labware_group .adapterLabwareId ] = OFF_DECK_LOCATION
173
+ new_offset_ids_by_id [labware_group .primaryLabwareId ] = None
174
+ new_offset_ids_by_id [labware_group .adapterLabwareId ] = None
175
+ else :
176
+ new_locations_by_id [labware_group .primaryLabwareId ] = OFF_DECK_LOCATION
177
+ new_offset_ids_by_id [labware_group .primaryLabwareId ] = None
178
+ if labware_group .lidLabwareId :
179
+ new_locations_by_id [labware_group .lidLabwareId ] = OnLabwareLocation (
180
+ labwareId = labware_group .primaryLabwareId
181
+ )
182
+ new_offset_ids_by_id [labware_group .lidLabwareId ] = None
183
+
184
+ for group in removed_labware :
185
+ _add_to_dicts (group )
103
186
104
187
state_update = (
105
- update_types .StateUpdate ().update_flex_stacker_labware_pool_count (
106
- params .moduleId , new_count
188
+ update_types .StateUpdate ()
189
+ .update_flex_stacker_contained_labware (
190
+ module_id = params .moduleId ,
191
+ contained_labware_bottom_first = new_stored_labware ,
192
+ )
193
+ .set_batch_labware_location (
194
+ new_locations_by_id = new_locations_by_id ,
195
+ new_offset_ids_by_id = new_offset_ids_by_id ,
107
196
)
108
197
)
109
198
@@ -115,28 +204,56 @@ async def execute(self, params: EmptyParams) -> SuccessData[EmptyResult]:
115
204
"The Primary Labware must be defined in the stacker pool."
116
205
)
117
206
207
+ original_locations = [
208
+ labware_locations_for_group (
209
+ group , [InStackerHopperLocation (moduleId = params .moduleId )]
210
+ )
211
+ for group in removed_labware
212
+ ]
213
+ new_locations = [
214
+ labware_locations_for_group (
215
+ group ,
216
+ [
217
+ NotOnDeckLocationSequenceComponent (
218
+ logicalLocationName = OFF_DECK_LOCATION
219
+ )
220
+ ],
221
+ )
222
+ for group in removed_labware
223
+ ]
224
+
118
225
return SuccessData (
119
- public = EmptyResult (
226
+ public = EmptyResult . model_construct (
120
227
count = new_count ,
121
- primaryLabwareURI = uri_from_details (
122
- stacker_state .pool_primary_definition .namespace ,
123
- stacker_state .pool_primary_definition .parameters .loadName ,
124
- stacker_state .pool_primary_definition .version ,
228
+ primaryLabwareURI = self ._state_view .labware .get_uri_from_definition (
229
+ stacker_state .pool_primary_definition
230
+ ),
231
+ adapterLabwareURI = self ._state_view .labware .get_uri_from_definition_unless_none (
232
+ stacker_state .pool_adapter_definition
233
+ ),
234
+ lidLabwareURI = self ._state_view .labware .get_uri_from_definition_unless_none (
235
+ stacker_state .pool_lid_definition
236
+ ),
237
+ storedLabware = new_stored_labware ,
238
+ removedLabware = removed_labware ,
239
+ originalPrimaryLabwareLocationSequences = primary_location_sequences (
240
+ original_locations
241
+ ),
242
+ originalAdapterLabwareLocationSequences = adapter_location_sequences_with_default (
243
+ original_locations , stacker_state .pool_adapter_definition
244
+ ),
245
+ originalLidLabwareLocationSequences = lid_location_sequences_with_default (
246
+ original_locations , stacker_state .pool_lid_definition
247
+ ),
248
+ newPrimaryLabwareLocationSequences = primary_location_sequences (
249
+ new_locations
250
+ ),
251
+ newAdapterLabwareLocationSequences = adapter_location_sequences_with_default (
252
+ new_locations , stacker_state .pool_adapter_definition
253
+ ),
254
+ newLidLabwareLocationSequences = lid_location_sequences_with_default (
255
+ new_locations , stacker_state .pool_lid_definition
125
256
),
126
- adapterLabwareURI = uri_from_details (
127
- stacker_state .pool_adapter_definition .namespace ,
128
- stacker_state .pool_adapter_definition .parameters .loadName ,
129
- stacker_state .pool_adapter_definition .version ,
130
- )
131
- if stacker_state .pool_adapter_definition is not None
132
- else None ,
133
- lidLabwareURI = uri_from_details (
134
- stacker_state .pool_lid_definition .namespace ,
135
- stacker_state .pool_lid_definition .parameters .loadName ,
136
- stacker_state .pool_lid_definition .version ,
137
- )
138
- if stacker_state .pool_lid_definition is not None
139
- else None ,
140
257
),
141
258
state_update = state_update ,
142
259
)
0 commit comments