@@ -1135,3 +1135,122 @@ def _reconfigure_nozzle_layout(start: str, back_l: str, front_r: str) -> NozzleM
1135
1135
_assert_and_pickup ("H1" , map )
1136
1136
map = _reconfigure_nozzle_layout ("A1" , "A1" , "A1" )
1137
1137
_assert_and_pickup ("B9" , map )
1138
+
1139
+
1140
+ def test_next_tip_automatic_tip_tracking_tiprack_limits (
1141
+ subject : TipStore ,
1142
+ supported_tip_fixture : pipette_definition .SupportedTipsDefinition ,
1143
+ load_labware_command : commands .LoadLabware ,
1144
+ pick_up_tip_command : commands .PickUpTip ,
1145
+ ) -> None :
1146
+ """Test tip tracking logic to ensure once a tiprack is consumed it returns None when consuming tips using multiple pipette configurations."""
1147
+ # Load labware
1148
+ subject .handle_action (
1149
+ actions .SucceedCommandAction (private_result = None , command = load_labware_command )
1150
+ )
1151
+
1152
+ # Load pipette
1153
+ load_pipette_command = commands .LoadPipette .construct ( # type: ignore[call-arg]
1154
+ result = commands .LoadPipetteResult (pipetteId = "pipette-id" )
1155
+ )
1156
+ load_pipette_private_result = commands .LoadPipettePrivateResult (
1157
+ pipette_id = "pipette-id" ,
1158
+ serial_number = "pipette-serial" ,
1159
+ config = LoadedStaticPipetteData (
1160
+ channels = 96 ,
1161
+ max_volume = 15 ,
1162
+ min_volume = 3 ,
1163
+ model = "gen a" ,
1164
+ display_name = "display name" ,
1165
+ flow_rates = FlowRates (
1166
+ default_aspirate = {},
1167
+ default_dispense = {},
1168
+ default_blow_out = {},
1169
+ ),
1170
+ tip_configuration_lookup_table = {15 : supported_tip_fixture },
1171
+ nominal_tip_overlap = {},
1172
+ nozzle_offset_z = 1.23 ,
1173
+ home_position = 4.56 ,
1174
+ nozzle_map = get_default_nozzle_map (PipetteNameType .P1000_96 ),
1175
+ back_left_corner_offset = Point (x = 1 , y = 2 , z = 3 ),
1176
+ front_right_corner_offset = Point (x = 4 , y = 5 , z = 6 ),
1177
+ ),
1178
+ )
1179
+ subject .handle_action (
1180
+ actions .SucceedCommandAction (
1181
+ private_result = load_pipette_private_result , command = load_pipette_command
1182
+ )
1183
+ )
1184
+
1185
+ def _get_next_and_pickup (nozzle_map : NozzleMap ) -> str | None :
1186
+ result = TipView (subject .state ).get_next_tip (
1187
+ labware_id = "cool-labware" ,
1188
+ num_tips = 0 ,
1189
+ starting_tip_name = None ,
1190
+ nozzle_map = nozzle_map ,
1191
+ )
1192
+ if result is not None :
1193
+ pick_up_tip = commands .PickUpTip .construct ( # type: ignore[call-arg]
1194
+ params = commands .PickUpTipParams .construct (
1195
+ pipetteId = "pipette-id" ,
1196
+ labwareId = "cool-labware" ,
1197
+ wellName = result ,
1198
+ ),
1199
+ result = commands .PickUpTipResult .construct (
1200
+ position = DeckPoint (x = 0 , y = 0 , z = 0 ), tipLength = 1.23
1201
+ ),
1202
+ )
1203
+
1204
+ subject .handle_action (
1205
+ actions .SucceedCommandAction (private_result = None , command = pick_up_tip )
1206
+ )
1207
+
1208
+ return result
1209
+
1210
+ # Configure nozzle for partial configurations
1211
+ configure_nozzle_layout_cmd = commands .ConfigureNozzleLayout .construct ( # type: ignore[call-arg]
1212
+ result = commands .ConfigureNozzleLayoutResult ()
1213
+ )
1214
+
1215
+ def _reconfigure_nozzle_layout (start : str , back_l : str , front_r : str ) -> NozzleMap :
1216
+ configure_nozzle_private_result = commands .ConfigureNozzleLayoutPrivateResult (
1217
+ pipette_id = "pipette-id" ,
1218
+ nozzle_map = NozzleMap .build (
1219
+ physical_nozzles = NINETY_SIX_MAP ,
1220
+ physical_rows = NINETY_SIX_ROWS ,
1221
+ physical_columns = NINETY_SIX_COLS ,
1222
+ starting_nozzle = start ,
1223
+ back_left_nozzle = back_l ,
1224
+ front_right_nozzle = front_r ,
1225
+ ),
1226
+ )
1227
+ subject .handle_action (
1228
+ actions .SucceedCommandAction (
1229
+ private_result = configure_nozzle_private_result ,
1230
+ command = configure_nozzle_layout_cmd ,
1231
+ )
1232
+ )
1233
+ return configure_nozzle_private_result .nozzle_map
1234
+
1235
+ map = _reconfigure_nozzle_layout ("A1" , "A1" , "A1" )
1236
+ for x in range (96 ):
1237
+ _get_next_and_pickup (map )
1238
+ assert _get_next_and_pickup (map ) is None
1239
+
1240
+ subject .handle_action (actions .ResetTipsAction (labware_id = "cool-labware" ))
1241
+ map = _reconfigure_nozzle_layout ("A12" , "A12" , "A12" )
1242
+ for x in range (96 ):
1243
+ _get_next_and_pickup (map )
1244
+ assert _get_next_and_pickup (map ) is None
1245
+
1246
+ subject .handle_action (actions .ResetTipsAction (labware_id = "cool-labware" ))
1247
+ map = _reconfigure_nozzle_layout ("H1" , "H1" , "H1" )
1248
+ for x in range (96 ):
1249
+ _get_next_and_pickup (map )
1250
+ assert _get_next_and_pickup (map ) is None
1251
+
1252
+ subject .handle_action (actions .ResetTipsAction (labware_id = "cool-labware" ))
1253
+ map = _reconfigure_nozzle_layout ("H12" , "H12" , "H12" )
1254
+ for x in range (96 ):
1255
+ _get_next_and_pickup (map )
1256
+ assert _get_next_and_pickup (map ) is None
0 commit comments