@@ -52,16 +52,26 @@ def introduction(pump_device) -> None:
5252
5353 logging .disable (logging .WARNING )
5454
55+ try :
56+ channel_pump_is_configured_for = config .get ("PWM_reverse" , pump_device .removesuffix ("_pump" ))
57+ except KeyError :
58+ echo (
59+ red (
60+ f"❌ { pump_device } is not present in config.ini. Please add it to the [PWM] section and try again."
61+ )
62+ )
63+ raise Abort ()
64+
5565 echo (
5666 f"""This routine will calibrate the { pump_device } on your current Pioreactor. You'll need:
5767
5868 1. A Pioreactor
59- 2. A vial placed on a scale with accuracy at least 0.1g
69+ 2. A vial is placed on a scale that measures weight with a minimum resolution of 0.1 grams.
6070 OR an accurate graduated cylinder.
6171 3. A larger container filled with water
62- 4. { pump_device } connected to the correct PWM channel (1, 2, 3, or 4) as determined in your configuration .
72+ 4. { pump_device } connected to the correct PWM channel { channel_pump_is_configured_for } .
6373
64- We will dose for a set duration, you'll measure how much volume was expelled, and then record it back here. After doing this a few times, we can construct a calibration line for this pump.
74+ We will dose for a set duration, you'll measure how much volume was expelled, and then record it back here. After doing this a few times, we can construct a calibration curve for this pump.
6575"""
6676 )
6777 confirm (green ("Proceed?" ), abort = True , default = True )
@@ -100,15 +110,8 @@ def setup(
100110 pump_device : PumpCalibrationDevices , execute_pump : Callable , hz : float , dc : float , unit : str
101111) -> None :
102112 # set up...
103- try :
104- channel_pump_is_configured_for = config .get ("PWM_reverse" , pump_device .removesuffix ("_pump" ))
105- except KeyError :
106- echo (
107- red (
108- f"❌ { pump_device } is not present in config.ini. Please add it to the [PWM] section and try again."
109- )
110- )
111- raise Abort ()
113+ channel_pump_is_configured_for = config .get ("PWM_reverse" , pump_device .removesuffix ("_pump" ))
114+
112115 clear ()
113116 echo ()
114117 echo (green (bold ("Step 2" )))
@@ -128,7 +131,7 @@ def setup(
128131
129132 while not confirm (green ("Ready to start pumping?" )):
130133 pass
131-
134+ echo ()
132135 echo (
133136 bold (
134137 "Press CTRL+C when the tubes are completely filled with water and there are no air pockets in the tubes."
@@ -163,6 +166,7 @@ def setup(
163166
164167
165168def choose_settings () -> tuple [float , float ]:
169+ clear ()
166170 hz = prompt (
167171 style (green ("Optional: Enter frequency of PWM. [enter] for default 250 hz" )),
168172 type = click .FloatRange (0.1 , 10000 ),
@@ -207,14 +211,8 @@ def plot_data(x, y, title, x_min=None, x_max=None, interpolation_curve=None, hig
207211
208212
209213def run_tests (
210- execute_pump : Callable ,
211- hz : float ,
212- dc : float ,
213- min_duration : float ,
214- max_duration : float ,
215- pump_device : PumpCalibrationDevices ,
216- unit : str ,
217- ) -> tuple [list [float ], list [float ]]:
214+ execute_pump : Callable , hz : float , dc : float , unit : str , mls_to_calibrate_for : list [float ]
215+ ) -> tuple [list [float ], list [float ], float , float ]:
218216 clear ()
219217 echo ()
220218 echo (green (bold ("Step 3" )))
@@ -232,6 +230,46 @@ def run_tests(
232230 recorded_data = {"x" : [], "y" : []},
233231 )
234232
233+ tracer_duration = 1.0
234+
235+ echo ("We will run the pump for a set amount of time, and you will measure how much liquid is expelled." )
236+ echo ("Use a small container placed on top of an accurate weighing scale." )
237+ echo ("Hold the end of the outflow tube above so the container catches the expelled liquid." )
238+ echo ()
239+
240+ while not confirm (style (green (f"Ready to test { tracer_duration :.2f} s?" ))):
241+ pass
242+
243+ execute_pump (
244+ duration = tracer_duration ,
245+ source_of_event = "pump_calibration" ,
246+ unit = get_unit_name (),
247+ experiment = get_testing_experiment_name (),
248+ calibration = empty_calibration ,
249+ )
250+
251+ while True :
252+ r = prompt (
253+ style (green ("Enter amount of water expelled (g or ml), or REDO" )),
254+ confirmation_prompt = style (green ("Repeat for confirmation" )),
255+ )
256+ if r == "REDO" :
257+ clear ()
258+ echo ()
259+ continue
260+
261+ try :
262+ tracer_ml = float (r )
263+ clear ()
264+ echo ()
265+ break
266+ except ValueError :
267+ echo (red ("Not a number - retrying." ))
268+
269+ # calculate min and max duration based on tracer_ml
270+ min_duration = min (mls_to_calibrate_for ) * 0.9 / tracer_ml * tracer_duration
271+ max_duration = max (mls_to_calibrate_for ) * 1.1 / tracer_ml * tracer_duration
272+
235273 results : list [float ] = []
236274 durations_to_test = [min_duration ] * 4 + [(min_duration + max_duration ) / 2 ] * 2 + [max_duration ] * 4
237275 n_samples = len (durations_to_test )
@@ -264,7 +302,7 @@ def run_tests(
264302 )
265303 )
266304 )
267- while not confirm (style (green (f"Ready to test { duration :.2f } s?" ))):
305+ while not confirm (style (green (f"Ready to test { duration :.1f } s?" ))):
268306 pass
269307
270308 execute_pump (
@@ -292,7 +330,7 @@ def run_tests(
292330 except ValueError :
293331 echo (red ("Not a number - retrying." ))
294332
295- return durations_to_test , results
333+ return durations_to_test , results , min_duration , max_duration
296334
297335
298336def save_results (
@@ -322,8 +360,28 @@ def save_results(
322360 return pump_calibration_result
323361
324362
363+ def get_user_calibrations () -> list [float ]:
364+ clear ()
365+ mls = []
366+ r = prompt (
367+ green ("Enter the volume you wish to calibrate around (mL). [enter] to use default 1.0 ml" ),
368+ default = 1.0 ,
369+ type = float ,
370+ )
371+ mls .append (float (r ))
372+ while click .confirm (green ("Do you want to add another value?" )):
373+ r = prompt (
374+ green ("Enter another volume you wish to calibrate around (mL)" ),
375+ default = 1.0 ,
376+ type = float ,
377+ )
378+ mls .append (float (r ))
379+
380+ return mls
381+
382+
325383def run_pump_calibration (
326- pump_device , min_duration : float = 0.40 , max_duration : float = 1.5
384+ pump_device ,
327385) -> structs .SimplePeristalticPumpCalibration :
328386 unit = get_unit_name ()
329387 experiment = get_assigned_experiment_name (unit )
@@ -345,19 +403,22 @@ def run_pump_calibration(
345403 raise ValueError ()
346404
347405 name = get_metadata_from_user (pump_device )
406+ mls_to_calibrate_for = get_user_calibrations ()
348407
349- is_ready = True
350- while is_ready :
408+ settings_are_correct = False
409+ while not settings_are_correct :
351410 hz , dc = choose_settings ()
352411 setup (pump_device , execute_pump , hz , dc , unit )
353412
354- is_ready = confirm (
413+ settings_are_correct = not confirm (
355414 style (green ("Do you want to change the frequency or duty cycle?" )),
356415 prompt_suffix = " " ,
357416 default = False ,
358417 )
359418
360- durations , volumes = run_tests (execute_pump , hz , dc , min_duration , max_duration , pump_device , unit )
419+ durations , volumes , min_duration , max_duration = run_tests (
420+ execute_pump , hz , dc , unit , mls_to_calibrate_for
421+ )
361422
362423 (slope , std_slope ), (
363424 bias ,
0 commit comments