@@ -32,110 +32,160 @@ def add_parameters(parameters: ParameterContext) -> None:
32
32
minimum = 1 ,
33
33
maximum = 4 ,
34
34
)
35
+ helpers .create_channel_parameter (parameters )
35
36
36
37
37
38
def run (ctx : ProtocolContext ) -> None :
38
39
"""Protocol."""
40
+ # Load parameters
39
41
number_of_plates = ctx .params .number_of_plates # type: ignore [attr-defined]
42
+ channels = ctx .params .channels # type: ignore [attr-defined]
40
43
# Plate Reader
41
44
plate_reader : AbsorbanceReaderContext = ctx .load_module (
42
45
helpers .abs_mod_str , "A3"
43
46
) # type: ignore[assignment]
44
47
hs : HeaterShakerContext = ctx .load_module (helpers .hs_str , "A1" ) # type: ignore[assignment]
45
48
hs_adapter = hs .load_adapter ("opentrons_universal_flat_adapter" )
46
- tube_rack = ctx .load_labware (
47
- "opentrons_10_tuberack_nest_4x50ml_6x15ml_conical" , "C2" , "Reagent Tube"
48
- )
49
- tartrazine_tube = tube_rack ["A1" ]
50
- water_tube_1 = tube_rack ["A4" ]
51
- water_tube_2 = tube_rack ["B3" ]
52
- sample_plate_1 = ctx .load_labware (
53
- "corning_96_wellplate_360ul_flat" , "D1" , "Sample Plate 1"
54
- )
55
- sample_plate_2 = ctx .load_labware (
56
- "corning_96_wellplate_360ul_flat" , "D2" , "Sample Plate 2"
57
- )
58
- sample_plate_3 = ctx .load_labware (
59
- "corning_96_wellplate_360ul_flat" , "C1" , "Sample Plate 3"
60
- )
61
- sample_plate_4 = ctx .load_labware (
62
- "corning_96_wellplate_360ul_flat" , "B1" , "Sample Plate 4"
63
- )
64
-
65
- sample_plate_list = [sample_plate_1 , sample_plate_2 , sample_plate_3 , sample_plate_4 ]
66
- tiprack_50_1 = ctx .load_labware ("opentrons_flex_96_tiprack_50ul" , "D3" )
67
- tiprack_50_2 = ctx .load_labware ("opentrons_flex_96_tiprack_50ul" , "C3" )
68
- tiprack_50_3 = ctx .load_labware ("opentrons_flex_96_tiprack_50ul" , "B3" )
69
- tiprack_50_4 = ctx .load_labware ("opentrons_flex_96_tiprack_50ul" , "B2" )
70
-
49
+ # Load Plates based off of number_of_plates parameter
50
+ available_deck_slots = ["D1" , "D2" , "C1" , "B1" ]
51
+ sample_plate_list = []
52
+ for plate_num , slot in zip (range (number_of_plates ), available_deck_slots ):
53
+ plate = ctx .load_labware (
54
+ "corning_96_wellplate_360ul_flat" , slot , f"Sample Plate { plate_num + 1 } "
55
+ )
56
+ sample_plate_list .append (plate )
57
+ available_tip_rack_slots = ["D3" , "C3" , "B3" , "B2" ]
58
+ # LOAD PIPETTES AND TIP RACKS
59
+ # 50 CHANNEL
60
+ tip_racks_50 = []
61
+ for plate_num , slot_2 in zip (range (number_of_plates ), available_tip_rack_slots ):
62
+ tiprack_50 = ctx .load_labware ("opentrons_flex_96_tiprack_50ul" , slot_2 )
63
+ tip_racks_50 .append (tiprack_50 )
64
+ p50 = ctx .load_instrument (f"flex_{ channels } _50" , "left" , tip_racks = tip_racks_50 )
65
+ # 1000 CHANNEL
71
66
tiprack_1000_1 = ctx .load_labware ("opentrons_flex_96_tiprack_1000ul" , "A2" )
72
- tip_racks = [tiprack_50_1 , tiprack_50_2 , tiprack_50_3 , tiprack_50_4 ]
73
-
74
- # Pipette
75
- p50 = ctx .load_instrument ("flex_1channel_50" , "left" , tip_racks = tip_racks )
76
67
p1000 = ctx .load_instrument (
77
- "flex_1channel_1000 " , "right" , tip_racks = [tiprack_1000_1 ]
68
+ f"flex_ { channels } _1000 " , "right" , tip_racks = [tiprack_1000_1 ]
78
69
)
70
+ # DETERMINE RESERVOIR BASED OFF # OF PIPETTE CHANNELS
71
+ # 1 CHANNEL = TUBE RACK
72
+ if p50 .active_channels == 1 :
73
+ reservoir = ctx .load_labware (
74
+ "opentrons_10_tuberack_nest_4x50ml_6x15ml_conical" , "C2" , "Reservoir"
75
+ )
76
+ water_max_vol = reservoir ["A3" ].max_volume - 500
77
+ reservoir_wells = reservoir .wells ()[6 :] # Skip first 4 bc they are 15ml
78
+ else :
79
+ # 8 CHANNEL = 12 WELL RESERVOIR
80
+ reservoir = ctx .load_labware ("nest_12_reservoir_15ml" , "C2" , "Reservoir" )
81
+ water_max_vol = reservoir ["A1" ].max_volume - 500
82
+ reservoir_wells = reservoir .wells ()[
83
+ 1 :
84
+ ] # Skip A1 as it's reserved for tartrazine
85
+
86
+ # LABEL RESERVOIR WELLS AND DETERMINE NEEDED LIQUID
87
+ tartrazine_well = reservoir ["A1" ]
88
+ # NEEDED TARTRAZINE
89
+ needed_tartrazine : float = (
90
+ float (number_of_plates ) * 96.0
91
+ ) * 10.0 + 1000.0 # loading extra as a safety factor
92
+ # NEEDED WATER
93
+ needed_water : float = (
94
+ float (number_of_plates ) * 96.0 * 250
95
+ ) # loading extra as a safety factor
96
+ # CALCULATING NEEDED # OF WATER WELLS
97
+ needed_wells = round (needed_water / water_max_vol )
98
+ water_wells = []
99
+ for i in range (needed_wells + 1 ):
100
+ water_wells .append (reservoir_wells [i ])
79
101
80
102
def _mix_tartrazine (pipette : InstrumentContext , well_to_probe : Well ) -> None :
81
103
"""Mix Tartrazine."""
104
+ # Mix step is needed to ensure tartrazine does not settle between plates.
82
105
pipette .pick_up_tip ()
83
106
top_of_tartrazine = helpers .find_liquid_height (pipette , well_to_probe )
84
107
for i in range (20 ):
85
108
p50 .aspirate (1 , well_to_probe .bottom (z = 1 ))
86
- p50 .dispense (1 , well_to_probe .bottom (z = top_of_tartrazine - 2 ))
109
+ p50 .dispense (1 , well_to_probe .bottom (z = top_of_tartrazine + 1 ))
87
110
pipette .return_tip ()
88
111
89
- # Probe wells
112
+ # LOAD LIQUIDS AND PROBE WELLS
90
113
liquid_vols_and_wells : Dict [str , List [Dict [str , Well | List [Well ] | float ]]] = {
91
- "Tartrazine" : [{"well" : tartrazine_tube , "volume" : 5.0 }],
92
- "Water" : [{"well" : [ water_tube_1 , water_tube_2 ], "volume" : 45.0 }],
114
+ "Tartrazine" : [{"well" : tartrazine_well , "volume" : needed_tartrazine }],
115
+ "Water" : [{"well" : water_wells , "volume" : water_max_vol }],
93
116
}
94
117
helpers .find_liquid_height_of_loaded_liquids (ctx , liquid_vols_and_wells , p50 )
95
-
118
+ tip_count = 1 * p50 .active_channels # number of 50 ul tip uses.
119
+ p50 .reset_tipracks ()
96
120
i = 0
97
121
all_percent_error_dict = {}
98
122
cv_dict = {}
99
- vol = 0.0
100
- tip_count = 0
123
+ vol = 0.0 # counter to track available water volume
124
+ water_tip_count = 0 * p1000 .active_channels # number of 1000 ul tip uses
125
+ well_num = 0 # index of well being used for water
101
126
for sample_plate in sample_plate_list [:number_of_plates ]:
102
- _mix_tartrazine (p50 , tartrazine_tube )
103
- tip_count += 1
104
- deck_locations = ["D1" , "D2" , "C1" , "B1" ]
105
- p1000 .pick_up_tip ()
106
- for well in sample_plate .wells ():
107
- if vol < 45000 :
108
- tube_of_choice = water_tube_1
127
+ return_location = sample_plate .parent
128
+ # Mix Tartrazine to ensure no settling as occurred
129
+ _mix_tartrazine (p50 , tartrazine_well )
130
+ tip_count += 1 * p50 .active_channels
131
+ # Determine list of wells to probe
132
+ if p50 .active_channels == 1 :
133
+ well_list = sample_plate .wells ()
134
+ elif p50 .active_channels == 8 :
135
+ well_list = sample_plate .rows ()[0 ]
136
+ for well in well_list :
137
+ p1000 .pick_up_tip ()
138
+ # Determine which water well to aspirate from.
139
+ if vol < water_max_vol - 6000 :
140
+ well_of_choice = water_wells [well_num ]
109
141
else :
110
- tube_of_choice = water_tube_2
142
+ well_num += 1
143
+ well_of_choice = water_wells [well_num ]
144
+ vol = 0.0
111
145
p50 .pick_up_tip ()
112
- p1000 .aspirate (190 , tube_of_choice )
146
+ p1000 .aspirate (190 , well_of_choice )
113
147
p1000 .air_gap (10 )
114
- p1000 .dispense (5 , well .top ())
148
+ p1000 .dispense (10 , well .top ())
115
149
p1000 .dispense (190 , well )
116
- vol += 190
117
- height = helpers .find_liquid_height (p50 , tartrazine_tube )
118
- p50 .aspirate (10 , tartrazine_tube .bottom (z = height ), rate = 0.15 )
150
+ # Two blow outs ensures water is completely removed from pipette
151
+ p1000 .blow_out (well .top ())
152
+ ctx .delay (minutes = 0.1 )
153
+ p1000 .blow_out (well .top ())
154
+ vol += 190 * p1000 .active_channels
155
+ # Probe to find liquid height of tartrazine to ensure correct amount is aspirated
156
+ height = helpers .find_liquid_height (p50 , tartrazine_well )
157
+ p50 .aspirate (10 , tartrazine_well .bottom (z = height ), rate = 0.15 )
119
158
p50 .air_gap (5 )
120
159
p50 .dispense (5 , well .top ())
121
160
p50 .dispense (10 , well .bottom (z = 0.5 ), rate = 0.15 )
122
161
p50 .blow_out ()
162
+ ctx .delay (minutes = 0.1 )
163
+ p50 .blow_out ()
123
164
p50 .return_tip ()
124
- tip_count += 1
125
- if tip_count >= (96 * 4 ):
165
+ tip_count += p50 . active_channels
166
+ if tip_count >= (96 * len ( tip_racks_50 ) ):
126
167
p50 .reset_tipracks ()
127
- p1000 .return_tip ()
168
+ tip_count = 0
169
+ p1000 .return_tip ()
170
+ water_tip_count += p1000 .active_channels
171
+ if water_tip_count >= 96 :
172
+ p1000 .reset_tipracks ()
173
+ water_tip_count = 0
174
+ # Move labware to heater shaker to be mixed
128
175
helpers .move_labware_to_hs (ctx , sample_plate , hs , hs_adapter )
129
176
helpers .set_hs_speed (ctx , hs , 1500 , 2.0 , True )
130
177
hs .open_labware_latch ()
178
+ # Initialize plate reader
131
179
plate_reader .close_lid ()
132
180
plate_reader .initialize ("single" , [450 ])
133
181
plate_reader .open_lid ()
182
+ # Move sample plate into plate reader
134
183
ctx .move_labware (sample_plate , plate_reader , use_gripper = True )
135
184
sample_plate_name = "sample plate_" + str (i + 1 )
136
185
csv_string = sample_plate_name + "_" + str (datetime .now ())
137
186
plate_reader .close_lid ()
138
187
result = plate_reader .read (csv_string )
188
+ # Calculate CV and % error of expected value.
139
189
for wavelength in result :
140
190
dict_of_wells = result [wavelength ]
141
191
readings_and_wells = dict_of_wells .items ()
@@ -163,12 +213,13 @@ def _mix_tartrazine(pipette: InstrumentContext, well_to_probe: Well) -> None:
163
213
"SD" : standard_deviation ,
164
214
"Avg Percent Error" : avg_percent_error ,
165
215
}
166
- ctx . comment ( f"------plate { sample_plate } . { cv_dict [ sample_plate_name ] } ------" )
216
+ # Move Plate back to original location
167
217
all_percent_error_dict [sample_plate_name ] = percent_error_dict
168
218
plate_reader .open_lid ()
169
- ctx .move_labware (sample_plate , deck_locations [i ], use_gripper = True )
219
+ ctx .comment (f"------plate { sample_plate } . { cv_dict [sample_plate_name ]} ------" )
220
+ ctx .move_labware (sample_plate , return_location , use_gripper = True )
170
221
i += 1
171
222
# Print percent error dictionary
172
223
ctx .comment ("Percent Error: " + str (all_percent_error_dict ))
173
224
# Print cv dictionary
174
- ctx .comment ("Plate Reader result : " + str (cv_dict ))
225
+ ctx .comment ("Plate Reader Result : " + str (cv_dict ))
0 commit comments