Skip to content

Commit fbd16f9

Browse files
committed
Merge branch 'release/1.4'
2 parents 46bc491 + 48c0d31 commit fbd16f9

File tree

80 files changed

+4377
-5426
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

80 files changed

+4377
-5426
lines changed

CHANGELOG

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
## Version 1.4
2+
Documentation:
3+
- Added user manual in spanish and english.
4+
- Added how to ethernet connect your robot.
5+
- Added how to calibrate.
6+
- Added ssh connection guide.
7+
8+
New features:
9+
- Voice messages language optional (spanish and english)
10+
- Added tip count reset option.
11+
- Added calibration scripts checking for all protocols.
12+
- Now beads dilution is optional in protocol 2 station A. #b2b5444
13+
- Only pause for empty trash if samples > 48 in protocol B. #406c79a
14+
- Added json generation with run info in each protocol. This will be used for api connection with openrobots web.
15+
- New labware configuration for ecogen deep well, added to station A and B protocols.
16+
17+
Protocol modifications:
18+
- Now incubation time in protocol B is 7 minutes.
19+
- Reduced height in beads mix in protocol 2 station A, as it was taking some air sometimes. #53789ad
20+
- Increased height in beads mix in protocol 1 station B, as it was too close to the bottom.
21+
- Increased height in aspirates on on the plate above the magdeck, as it was sometimes touching the bottom.
22+
- Protocol now B starts with magdeck off. #6031d94
23+
- Fixed issue where m300 would go too deep and not aspire correctly in elution buffer. #40410be
24+
- Fixed issue where m300 would not aspirate correctly in all wells in supernatant removal, washes an elution when magnet is engaged. Aspiration height is increase to 1.5.
25+
26+
Bug fixes:
27+
- Fixed tip not dropping tip in p300 (protocol C) #9280ae8
28+
- Fixed correct pick up and drop tip for correct tip count for negative control (protocol C) #3483d15
29+
- Fixed correct drop tip for p300 (protocol C) #2e6cca7
30+
- Fixed tip count issue when only one pipette is used. #80b9567

experiments/20200427-stationA_protocol1_buffer_S3/stationA_protocol1_buffer_S3.ot2.apiv2.py calibration_check/stationA_protocol1_buffer_S3_calibration.py

+101-46
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
1-
from opentrons.types import Point
21
from opentrons import protocol_api
2+
from opentrons.types import Point
33
from opentrons.drivers.rpi_drivers import gpio
44
import time
55
import math
6-
import json
76
import os
7+
import subprocess
8+
import json
89

910
# Metadata
1011
metadata = {
11-
'protocolName': 'S3 Station A Protocol 1 buffer Version 1',
12+
'protocolName': 'Calibration check for S3 Station A Protocol 1 buffer Version 1',
1213
'author': 'Sara <[email protected]>, Miguel <[email protected]>',
1314
'source': 'Custom Protocol Request',
1415
'apiLevel': '2.3'
@@ -23,6 +24,8 @@
2324
DESTINATION_LABWARE = 'opentrons plastic 2ml tubes'
2425
DEST_TUBE = '2ml tubes'
2526
VOLUME_BUFFER = 300
27+
LANGUAGE = 'esp'
28+
RESET_TIPCOUNT = False
2629

2730
# End Parameters to adapt the protocol
2831

@@ -67,30 +70,70 @@
6770
'2ml tubes': 4
6871
}
6972

73+
LANGUAGE_DICT = {
74+
'esp': 'esp',
75+
'eng': 'eng'
76+
}
77+
78+
if LANGUAGE_DICT[LANGUAGE] == 'eng':
79+
VOICE_FILES_DICT = {
80+
'start': './data/sounds/started_process.mp3',
81+
'finish': './data/sounds/finished_process.mp3',
82+
'close_door': './data/sounds/close_door.mp3',
83+
'replace_tipracks': './data/sounds/replace_tipracks.mp3',
84+
'empty_trash': './data/sounds/empty_trash.mp3'
85+
}
86+
elif LANGUAGE_DICT[LANGUAGE] == 'esp':
87+
VOICE_FILES_DICT = {
88+
'start': './data/sounds/started_process_esp.mp3',
89+
'finish': './data/sounds/finished_process_esp.mp3',
90+
'close_door': './data/sounds/close_door_esp.mp3',
91+
'replace_tipracks': './data/sounds/replace_tipracks_esp.mp3',
92+
'empty_trash': './data/sounds/empty_trash_esp.mp3'
93+
}
94+
7095
# Function definitions
7196
def check_door():
7297
return gpio.read_window_switches()
7398

7499
def confirm_door_is_closed():
75-
#Check if door is opened
76-
if check_door() == False:
77-
#Set light color to red and pause
78-
gpio.set_button_light(1,0,0)
79-
robot.pause(f"Please, close the door")
80-
time.sleep(3)
81-
confirm_door_is_closed()
82-
else:
83-
#Set light color to green
84-
gpio.set_button_light(0,1,1)
100+
if not robot.is_simulating():
101+
#Check if door is opened
102+
if check_door() == False:
103+
#Set light color to red and pause
104+
gpio.set_button_light(1,0,0)
105+
robot.pause()
106+
voice_notification('close_door')
107+
time.sleep(5)
108+
confirm_door_is_closed()
109+
else:
110+
#Set light color to green
111+
gpio.set_button_light(0,1,0)
85112

86113
def finish_run():
114+
voice_notification('finish')
87115
#Set light color to blue
88116
gpio.set_button_light(0,0,1)
89117

118+
def voice_notification(action):
119+
if not robot.is_simulating():
120+
fname = VOICE_FILES_DICT[action]
121+
if os.path.isfile(fname) is True:
122+
subprocess.run(
123+
['mpg123', fname],
124+
stdout=subprocess.PIPE,
125+
stderr=subprocess.PIPE
126+
)
127+
else:
128+
robot.comment(f"Sound file does not exist. Call the technician")
129+
130+
def reset_tipcount():
131+
os.remove('/data/A/tip_log.json', 'w')
90132

91133
def retrieve_tip_info(pip,tipracks,file_path = '/data/A/tip_log.json'):
92134
global tip_log
93135
if not tip_log['count'] or pip not in tip_log['count']:
136+
tip_log['count'][pip] = 0
94137
if not robot.is_simulating():
95138
if os.path.isfile(file_path):
96139
with open(file_path) as json_file:
@@ -99,12 +142,8 @@ def retrieve_tip_info(pip,tipracks,file_path = '/data/A/tip_log.json'):
99142
tip_log['count'][pip] = data['tips1000']
100143
elif 'P300' in str(pip):
101144
tip_log['count'][pip] = data['tips300']
102-
else:
103-
tip_log['count'][pip] = 0
104-
else:
105-
tip_log['count'][pip] = 0
106-
else:
107-
tip_log['count'][pip] = 0
145+
elif 'P20' in str(pip):
146+
tip_log['count'][pip] = data['tips20']
108147

109148
if "8-Channel" in str(pip):
110149
tip_log['tips'][pip] = [tip for rack in tipracks for tip in rack.rows()[0]]
@@ -118,12 +157,15 @@ def retrieve_tip_info(pip,tipracks,file_path = '/data/A/tip_log.json'):
118157
def save_tip_info(file_path = '/data/A/tip_log.json'):
119158
data = {}
120159
if not robot.is_simulating():
121-
os.rename(file_path,file_path + ".bak")
160+
if os.path.isfile(file_path):
161+
os.rename(file_path,file_path + ".bak")
122162
for pip in tip_log['count']:
123163
if "P1000" in str(pip):
124164
data['tips1000'] = tip_log['count'][pip]
125165
elif "P300" in str(pip):
126166
data['tips300'] = tip_log['count'][pip]
167+
elif "P20" in str(pip):
168+
data['tips20'] = tip_log['count'][pip]
127169

128170
with open(file_path, 'a+') as outfile:
129171
json.dump(data, outfile)
@@ -135,21 +177,27 @@ def pick_up(pip,tiprack):
135177
tip_log = {}
136178
tip_log = retrieve_tip_info(pip,tiprack)
137179
if tip_log['count'][pip] == tip_log['max'][pip]:
180+
voice_notification('replace_tipracks')
138181
robot.pause('Replace ' + str(pip.max_volume) + 'µl tipracks before \
139182
resuming.')
183+
confirm_door_is_closed()
140184
pip.reset_tipracks()
141185
tip_log['count'][pip] = 0
142186
pip.pick_up_tip(tip_log['tips'][pip][tip_log['count'][pip]])
143187
tip_log['count'][pip] += 1
144188

145189
def drop(pip):
146190
global switch
147-
side = 1 if switch else -1
148-
drop_loc = robot.loaded_labwares[12].wells()[0].top().move(Point(x=side*20))
149-
pip.drop_tip(drop_loc,home_after=False)
150-
switch = not switch
191+
if "8-Channel" not in str(pip):
192+
side = 1 if switch else -1
193+
drop_loc = robot.loaded_labwares[12].wells()[0].top().move(Point(x=side*20))
194+
pip.drop_tip(drop_loc,home_after=False)
195+
switch = not switch
196+
else:
197+
drop_loc = robot.loaded_labwares[12].wells()[0].top().move(Point(x=20))
198+
pip.drop_tip(drop_loc,home_after=False)
151199

152-
def transfer_buffer(bf_tube, dests, volume, pip,tiprack):
200+
def transfer_buffer(bf_tube, dests, pip,tiprack):
153201
max_trans_per_asp = 3 # 1000/VOLUME_BUFFER = 3
154202
split_ind = [ind for ind in range(0, len(dests), max_trans_per_asp)]
155203
dest_sets = [dests[split_ind[i]:split_ind[i+1]]
@@ -167,16 +215,17 @@ def transfer_buffer(bf_tube, dests, volume, pip,tiprack):
167215
def run(ctx: protocol_api.ProtocolContext):
168216
global robot
169217
robot = ctx
170-
# confirm door is close
171-
if not ctx.is_simulating():
172-
confirm_door_is_closed()
218+
219+
# check if tipcount is being reset
220+
if RESET_TIPCOUNT:
221+
reset_tipcount()
173222

174223
# define tips
175-
tips1000 = [ctx.load_labware('opentrons_96_filtertiprack_1000ul',
224+
tips1000 = [robot.load_labware('opentrons_96_filtertiprack_1000ul',
176225
3, '1000µl tiprack')]
177226

178227
# define pipettes
179-
p1000 = ctx.load_instrument('p1000_single_gen2', 'left', tip_racks=tips1000)
228+
p1000 = robot.load_instrument('p1000_single_gen2', 'left', tip_racks=tips1000)
180229

181230

182231
# check buffer labware type
@@ -185,7 +234,7 @@ def run(ctx: protocol_api.ProtocolContext):
185234
following:\nopentrons plastic 50ml tubes')
186235

187236
# load mastermix labware
188-
buffer_rack = ctx.load_labware(
237+
buffer_rack = robot.load_labware(
189238
BUFFER_LW_DICT[BUFFER_LABWARE], '10',
190239
BUFFER_LABWARE)
191240

@@ -196,30 +245,36 @@ def run(ctx: protocol_api.ProtocolContext):
196245

197246
# load elution labware
198247
dest_racks = [
199-
ctx.load_labware(DESTINATION_LW_DICT[DESTINATION_LABWARE], slot,
248+
robot.load_labware(DESTINATION_LW_DICT[DESTINATION_LABWARE], slot,
200249
'Destination tubes labware ' + str(i+1))
201250
for i, slot in enumerate(['4', '1', '5', '2'])
202251
]
203252

204253
# setup sample sources and destinations
205254
bf_tubes = buffer_rack.wells()[:4]
206255
number_racks = math.ceil(NUM_SAMPLES/len(dest_racks[0].wells()))
256+
dests = [
257+
tube
258+
for rack in dest_racks
259+
for tube in rack.wells()
260+
]
207261

208-
# dest_sets is a list of lists. Each list is the destination well for each rack
209-
# example: [[tube1,tube2,...tube24](first rack),[tube1,tube2(second rack),...]
210-
dest_sets = [
211-
[tube
212-
for rack in dest_racks
213-
for tube in rack.wells()
214-
][:NUM_SAMPLES][i*len(dest_racks[0].wells()):(i+1)*len(dest_racks[0].wells())]
215-
for i in range(number_racks)
216-
]
262+
# check top-left and bottom-right well of each labware with each pipette which uses them
263+
pick_up(p1000, tips1000)
264+
for position in [bf_tubes[0], bf_tubes[-1]]:
265+
p1000.move_to(position.top())
266+
robot.pause(f"Is it at the top of the well?")
267+
p1000.aspirate(800, position.bottom(2))
268+
p1000.move_to(position.top())
269+
robot.pause(f"Did it aspirate correctly?")
270+
p1000.dispense(800, position.top(-20))
271+
p1000.move_to(position.top())
272+
robot.pause(f"Did it dispense all the liquid?")
273+
for position in [dests[0], dests[23], dests[24], dests[47], dests[48], dests[71], dests[72], dests[-1]]:
274+
p1000.move_to(position.top())
275+
robot.pause(f"Is it at the top of the well?")
276+
drop(p1000)
217277

218-
# transfer buffer to tubes
219-
for bf_tube,dests in zip(bf_tubes,dest_sets):
220-
transfer_buffer(bf_tube, dests,VOLUME_BUFFER, p1000, tips1000)
221278

222279
# track final used tip
223280
save_tip_info()
224-
225-
finish_run()

0 commit comments

Comments
 (0)