1
1
"""Test Droplets."""
2
2
from asyncio import sleep
3
3
from time import time
4
- from typing import List , Union , Tuple , Optional , Dict
4
+ from typing import List , Union , Tuple , Optional , Dict , Literal
5
5
6
6
from opentrons .hardware_control .ot3api import OT3API
7
7
from opentrons .hardware_control .motion_utilities import target_position_from_relative
16
16
from hardware_testing .opentrons_api import helpers_ot3
17
17
from hardware_testing .opentrons_api .types import OT3Mount , Point , Axis
18
18
19
- TIP_VOLUME = 1000
20
- ASPIRATE_VOLUME = [1000 , 5 ]
21
19
NUM_SECONDS_TO_WAIT = 30
22
20
HOVER_HEIGHT_MM = 50
23
21
DEPTH_INTO_RESERVOIR_FOR_ASPIRATE = - 24
24
22
DEPTH_INTO_RESERVOIR_FOR_DISPENSE = DEPTH_INTO_RESERVOIR_FOR_ASPIRATE
25
23
26
- TIP_RACK_LABWARE = f"opentrons_flex_96_tiprack_{ TIP_VOLUME } ul"
27
24
RESERVOIR_LABWARE = "nest_1_reservoir_195ml"
28
25
29
- TIP_RACK_96_SLOT = 10
26
+ TIP_RACK_96_SLOT = 4
30
27
TIP_RACK_PARTIAL_SLOT = 5
31
28
RESERVOIR_SLOT = 2
32
29
TRASH_SLOT = 12
@@ -86,31 +83,31 @@ def get_reservoir_nominal() -> Point:
86
83
return reservoir_a1_nominal
87
84
88
85
89
- def get_tiprack_96_nominal () -> Point :
86
+ def get_tiprack_96_nominal (pipette : Literal [ 200 , 1000 ] ) -> Point :
90
87
"""Get nominal tiprack position for 96-tip pick-up."""
91
88
tip_rack_a1_nominal = helpers_ot3 .get_theoretical_a1_position (
92
- TIP_RACK_96_SLOT , TIP_RACK_LABWARE
89
+ TIP_RACK_96_SLOT , f"opentrons_flex_96_tiprack_ { pipette } ul"
93
90
)
94
91
return tip_rack_a1_nominal + Point (z = TIP_RACK_96_ADAPTER_HEIGHT )
95
92
96
93
97
- def get_tiprack_partial_nominal () -> Point :
94
+ def get_tiprack_partial_nominal (pipette : Literal [ 200 , 1000 ] ) -> Point :
98
95
"""Get nominal tiprack position for partial-tip pick-up."""
99
96
tip_rack_a1_nominal = helpers_ot3 .get_theoretical_a1_position (
100
- TIP_RACK_PARTIAL_SLOT , TIP_RACK_LABWARE
97
+ TIP_RACK_PARTIAL_SLOT , f"opentrons_flex_96_tiprack_ { pipette } ul"
101
98
)
102
99
return tip_rack_a1_nominal
103
100
104
101
105
102
async def aspirate_and_wait (
106
- api : OT3API , reservoir : Point , aspirate_value , seconds : int = 30
103
+ api : OT3API , reservoir : Point , volume : int , seconds : int = 30
107
104
) -> Tuple [bool , float ]:
108
105
"""Aspirate and wait."""
109
106
await helpers_ot3 .move_to_arched_ot3 (api , OT3Mount .LEFT , reservoir )
110
107
await api .move_to (
111
108
OT3Mount .LEFT , reservoir + Point (z = DEPTH_INTO_RESERVOIR_FOR_ASPIRATE )
112
109
)
113
- await api .aspirate (OT3Mount .LEFT , aspirate_value )
110
+ await api .aspirate (OT3Mount .LEFT , volume )
114
111
await api .move_to (OT3Mount .LEFT , reservoir + Point (z = HOVER_HEIGHT_MM ))
115
112
116
113
start_time = time ()
@@ -136,16 +133,16 @@ async def aspirate_and_wait(
136
133
return result , duration_seconds
137
134
138
135
139
- async def _drop_tip (api : OT3API , trash : Point ) -> None :
136
+ async def _drop_tip (api : OT3API , trash : Point , pipette : Literal [ 200 , 1000 ] ) -> None :
140
137
print ("drop in trash" )
141
138
await helpers_ot3 .move_to_arched_ot3 (api , OT3Mount .LEFT , trash + Point (z = 20 ))
142
139
await api .move_to (OT3Mount .LEFT , trash )
143
140
await api .drop_tip (OT3Mount .LEFT )
144
141
# NOTE: a FW bug (as of v14) will sometimes not fully drop tips.
145
142
# so here we ask if the operator needs to try again
146
- # while not api.is_simulator and ui.get_user_answer("try dropping again"):
147
- # await api.add_tip(OT3Mount.LEFT, helpers_ot3.get_default_tip_length(TIP_VOLUME ))
148
- # await api.drop_tip(OT3Mount.LEFT)
143
+ while not api .is_simulator and ui .get_user_answer ("try dropping again" ):
144
+ api .add_tip (OT3Mount .LEFT , helpers_ot3 .get_default_tip_length (pipette ))
145
+ await api .drop_tip (OT3Mount .LEFT )
149
146
await api .home_z (OT3Mount .LEFT )
150
147
151
148
@@ -164,32 +161,36 @@ async def _partial_pick_up_z_motion(
164
161
await api ._update_position_estimation ([Axis .Z_L ])
165
162
166
163
167
- async def _partial_pick_up (api : OT3API , position : Point , current : float ) -> None :
164
+ async def _partial_pick_up (
165
+ api : OT3API , position : Point , current : float , pipette : Literal [200 , 1000 ]
166
+ ) -> None :
168
167
await helpers_ot3 .move_to_arched_ot3 (
169
168
api ,
170
169
OT3Mount .LEFT ,
171
170
position ,
172
171
safe_height = position .z + 10 ,
173
172
)
174
173
await _partial_pick_up_z_motion (api , current = current , distance = 13 , speed = 5 )
175
- await api .add_tip (OT3Mount .LEFT , helpers_ot3 .get_default_tip_length (TIP_VOLUME ))
174
+ api .add_tip (OT3Mount .LEFT , helpers_ot3 .get_default_tip_length (pipette ))
176
175
await api .prepare_for_aspirate (OT3Mount .LEFT )
177
176
await api .home_z (OT3Mount .LEFT )
178
177
179
178
180
- async def run (api : OT3API , report : CSVReport , section : str ) -> None :
179
+ async def run (
180
+ api : OT3API , report : CSVReport , section : str , pipette : Literal [200 , 1000 ]
181
+ ) -> None :
181
182
"""Run."""
182
183
# GATHER NOMINAL POSITIONS
183
184
trash_nominal = get_trash_nominal ()
184
- tip_rack_96_a1_nominal = get_tiprack_96_nominal ()
185
+ tip_rack_96_a1_nominal = get_tiprack_96_nominal (pipette )
185
186
# tip_rack_partial_a1_nominal = get_tiprack_partial_nominal()
186
187
reservoir_a1_nominal = get_reservoir_nominal ()
187
188
reservoir_a1_actual : Optional [Point ] = None
188
189
189
190
async def _find_reservoir_pos () -> None :
190
191
nonlocal reservoir_a1_actual
191
- # if reservoir_a1_actual: # re-find reservoir position for 5ul
192
- # return
192
+ if reservoir_a1_actual :
193
+ return
193
194
# SAVE RESERVOIR POSITION
194
195
ui .print_header ("JOG to TOP of RESERVOIR" )
195
196
print ("jog tips to the TOP of the RESERVOIR" )
@@ -199,37 +200,47 @@ async def _find_reservoir_pos() -> None:
199
200
await helpers_ot3 .jog_mount_ot3 (api , OT3Mount .LEFT )
200
201
reservoir_a1_actual = await api .gantry_position (OT3Mount .LEFT )
201
202
202
- result = True
203
- for test_volume in ASPIRATE_VOLUME :
204
- answer = ui .get_user_answer (f"Test { test_volume } uL" )
205
- if not answer :
206
- continue
207
- tip_volume = 50 if test_volume <= 50 else 1000
208
- # PICK-UP 96 TIPS
203
+ # PICK-UP 96 TIPS
204
+ droplets_result = True
205
+ for trial in range (2 ):
209
206
ui .print_header ("JOG to 96-Tip RACK" )
207
+ if trial == 0 :
208
+ tip_rack = str (pipette ) + "ul"
209
+ test_volume : int = pipette
210
+ else :
211
+ tip_rack = "50ul"
212
+ test_volume = 1 if pipette == 200 else 5
210
213
if not api .is_simulator :
211
- ui .get_user_ready (f"picking up tips, place tip-rack { tip_volume } on slot { TIP_RACK_96_SLOT } " )
214
+ ui .get_user_ready (f"ADD 96 tip-rack- { tip_rack } to slot # { TIP_RACK_96_SLOT } " )
212
215
await helpers_ot3 .move_to_arched_ot3 (
213
216
api , OT3Mount .LEFT , tip_rack_96_a1_nominal + Point (z = 30 )
214
217
)
215
218
await helpers_ot3 .jog_mount_ot3 (api , OT3Mount .LEFT )
216
-
217
- await api .pick_up_tip (OT3Mount .LEFT , helpers_ot3 .get_default_tip_length (tip_volume ))
219
+ print ("picking up tips" )
220
+ await api .pick_up_tip (
221
+ OT3Mount .LEFT , helpers_ot3 .get_default_tip_length (pipette )
222
+ )
218
223
await api .home_z (OT3Mount .LEFT )
219
- if not api .is_simulator :
220
- ui .get_user_ready ("about to move to RESERVOIR" )
221
- # TEST DROPLETS for 96 TIPS
222
- ui .print_header ("96 Tips: ASPIRATE and WAIT" )
223
- await _find_reservoir_pos ()
224
+ if reservoir_a1_actual is None :
225
+ if not api .is_simulator :
226
+ ui .get_user_ready ("about to move to RESERVOIR" )
227
+
228
+ # TEST DROPLETS for 96 TIPS
229
+ ui .print_header ("96 Tips: ASPIRATE and WAIT" )
230
+ await _find_reservoir_pos ()
224
231
assert reservoir_a1_actual
225
- ret , duration = await aspirate_and_wait (
226
- api , reservoir_a1_actual , test_volume , seconds = NUM_SECONDS_TO_WAIT
232
+ result , duration = await aspirate_and_wait (
233
+ api ,
234
+ reservoir_a1_actual ,
235
+ test_volume ,
236
+ seconds = NUM_SECONDS_TO_WAIT ,
227
237
)
228
- result = result & ret
238
+ droplets_result = droplets_result & result
239
+ await _drop_tip (api , trash_nominal , pipette )
229
240
await api .home_z (OT3Mount .LEFT )
230
- await _drop_tip ( api , trash_nominal )
231
- report ( section , "droplets-96-tips" , [duration , CSVResult .from_bool (result )])
232
-
241
+ report (
242
+ section , "droplets-96-tips" , [duration , CSVResult .from_bool (droplets_result )]
243
+ )
233
244
234
245
# if not api.is_simulator:
235
246
# ui.get_user_ready(f"REMOVE 96 tip-rack from slot #{TIP_RACK_96_SLOT}")
0 commit comments