Skip to content

Commit 014bf45

Browse files
docs
1 parent 69f30e2 commit 014bf45

File tree

3 files changed

+41
-23
lines changed

3 files changed

+41
-23
lines changed

developer-guide/25-Calibrations/01-Calibrations.md

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ Continuing our pH example, the calibration type for it might look like:
3939
```python
4040
from pioreactor.structs import CalibrationBase # see this class for the full list of fields
4141

42-
class PHCalibration(CalibrationBase, kw_only=True, tag="ph"):
42+
class PHBufferCalibration(CalibrationBase, kw_only=True, tag="ph_buffer"):
4343
x: str = "pH" # required
4444
y: str = "Voltage" # required
4545

@@ -55,7 +55,15 @@ class PHCalibration(CalibrationBase, kw_only=True, tag="ph"):
5555
return self.x_to_y(ph)
5656
```
5757

58-
The `predict` and `ipredict` functions are used to convert between the two variables. The `i` in `ipredict` stands for "inverse".
58+
The `tag` should be unique for this calibration type. For example, if we instead had another pH calibration type that used optics instead of buggers, we could define another pH calibration type as follows:
59+
60+
```python
61+
class PHOpticsCalibration(CalibrationBase, kw_only=True, tag="optical_ph"):
62+
x: str = "pH"
63+
y: str = "Lumens"
64+
```
65+
66+
It's optional, but we also defined some helper functions `voltage_to_ph` and `ph_to_voltage` to easily map between the variables. Internally, They call `x_to_y` and `y_to_x` functions which are always available on a calibration object. They do the hard math behind mapping variables to each other.
5967

6068

6169

@@ -69,23 +77,25 @@ Define a `CalibrationProtocol` subclass that will hold metadata for your protoco
6977
```python
7078
from pioreactor.calibrations import CalibrationProtocol
7179
from pioreactor.utils.timing import current_utc_datetime
80+
from pioreactor import whoami
81+
7282

7383
class BufferBasedPHProtocol(CalibrationProtocol):
7484
target_device = "ph"
7585
protocol_name = "buffer_based"
7686
description = "Calibrate the pH sensor using buffer solutions"
7787

78-
def run(self, target_device: str) -> PHCalibration:
79-
return run_ph_calibration()
88+
def run(self, target_device: str):
89+
return run_ph_buffer_calibration()
8090

8191

82-
def run_ph_calibration() -> PHCalibration:
92+
def run_ph_buffer_calibration():
8393
# run the calibration, look at other calibration examples to re use code.
8494
...
8595

86-
return PHCalibration(
96+
return PHBufferCalibration(
8797
calibration_name="ph_calibration",
88-
calibrated_on_pioreactor_unit="unit1",
98+
calibrated_on_pioreactor_unit=whoami.get_unit_name(),
8999
created_at=current_utc_datetime(),
90100
curve_data_=[2, 3, 5],
91101
curve_type="poly",
@@ -104,39 +114,41 @@ You can add your code to the `~/.pioreactor/plugins` folder on the Pioreactor, i
104114
and UI. To complete our pH example, add the following to a new Python file in the `~/.pioreactor/plugins` folder:
105115

106116
```python
117+
from __future__ import annotations
107118
from pioreactor.calibrations import CalibrationProtocol
108119
from pioreactor.structs import CalibrationBase
109120
from pioreactor.utils.timing import current_utc_datetime
121+
from pioreactor import whoami
110122
import typing as t
111123

112-
class PHCalibration(CalibrationBase, kw_only=True, tag="ph"):
124+
class PHBufferCalibration(CalibrationBase, kw_only=True, tag="ph_buffer"):
125+
x: str = "pH" # required
126+
y: str = "Voltage" # required
127+
113128
buffer_solution: t.Literal["4.01", "7.00", "10.01"]
114129
electrode_type: str
115-
x: str = "pH"
116-
y: str = "Voltage"
117130

118-
def voltage_to_ph(self, voltage: float) -> float:
131+
def voltage_to_ph(self, voltage: float):
119132
return self.y_to_x(voltage)
120133

121-
def ph_to_voltage(self, ph: float) -> float:
134+
def ph_to_voltage(self, ph: float):
122135
return self.x_to_y(ph)
123136

124137
class BufferBasedPHProtocol(CalibrationProtocol):
125138
target_device = "ph"
126139
protocol_name = "buffer_based"
127140
description = "Calibrate the pH sensor using buffer solutions"
128141

129-
def run(self, target_device: str) -> PHCalibration:
130-
return run_ph_calibration()
131-
142+
def run(self, target_device: str):
143+
return run_ph_buffer_calibration()
132144

133-
def run_ph_calibration() -> PHCalibration:
134-
# run the calibration
145+
def run_ph_buffer_calibration():
146+
# run the calibration to get data
135147
...
136148

137-
return PHCalibration(
149+
return PHBufferCalibration(
138150
calibration_name="ph_calibration",
139-
calibrated_on_pioreactor_unit="unit1",
151+
calibrated_on_pioreactor_unit=whoami.get_unit_name(),
140152
created_at=current_utc_datetime(),
141153
curve_data_=[2, 3, 5],
142154
curve_type="poly",
@@ -158,6 +170,6 @@ pio calibrations run --device ph
158170

159171
- use the Python library `click` to create an interactive CLI for your calibration protocol.
160172
- the pair `(device, calibration_name)` must be unique. The final directory structure looks like `~/.pioreactor/storage/calibrations/<device>/<calibration_name>.yaml`
161-
- The `x` variable should be the independent variable - the variable that can (in theory) be set by you, and the response variable `y` follows. For example, in the default OD calibration, the independent variable is the OD, and the dependent variable is the Pioreactor's sensor's voltage. This is because we can vary the OD as we wish (add more culture...), and the Pioreactor's sensor will detect different values.
162-
- Another way to look at this is: "where does error exist"? Typically, there will be error "measurement" variable (voltage for OD calibration, RPM measurement for stirring calibration, etc.)
173+
- The `x` variable should be the independent variable - the variable that can (in theory) be set by you, and the measurement variable `y` follows. For example, in the default OD calibration, the independent variable is the OD, and the dependent variable is the Pioreactor's sensor's voltage. This is because we can vary the OD as we wish (add more culture...), and the Pioreactor's sensor will detect different values.
174+
- Another way to look at this is: "where does error exist"? Typically, there will be error in the "measurement" variable (voltage for OD calibration, RPM measurement for stirring calibration, etc.). In practice, we only have the measurement variable, and wish to go "back" to the original variable.
163175

user-guide/03-Extending your Pioreactor/04-Experiment Profiles/03-start-stop-profiles.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ From the command line, you can run:
3535
pio kill --job-name experiment_profiles
3636
```
3737

38-
This will actually kill _all_ experiment profiles running. To specify a specific profile, use it's job-id:
38+
This will actually kill _all_ experiment profiles running. To specify a specific profile, use its job-id:
3939

4040
```bash
4141
pio kill --job-id <job-id>

user-guide/29-Automations/02-dosing-automations.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,13 @@ When liquid is added, say 1ml, the volume rises an additional 1ml. Then 1ml of l
9292

9393
To further avoid overflow, we limit how much liquid is added in a single pump cycle. If the amount of liquid to be added is greater than the `max_dose_volume`, then the liquid is divided into smaller doses (halved until those new doses are less than `max_subdose` parameter), with the waste-pump run in between to avoid overflow. These small doses are called _subdoses_. You can change the maximum subdose value with the parameter `max_subdose`, see below.
9494

95+
### Volume parameters
96+
97+
98+
- **Initial vial volume**: this is how much liquid is initially in the vial
99+
- **Max vial volume**: the efflux tube's position determines the maximum volume your liquid volume will reach.
100+
101+
95102
### Configuration parameters
96103

97104
You can edit these parameters in your config.ini files.
@@ -101,7 +108,6 @@ You can edit these parameters in your config.ini files.
101108

102109
- `pause_between_subdoses_seconds`: time to wait between doses - this is useful if you want to be sure the newly added liquid is sufficiently mixed before running the waste pump.
103110
- `waste_removal_multiplier`: the amount of additional time to run the waste pump after the influx pump has run. This is to ensure that the volume of liquid in the vial never exceeds the end of the efflux tube. Ex: if media ran for `0.75` seconds, then the waste will run for `waste_removal_multiplier * 0.75 seconds`
104-
- `max_volume_to_stop`: if the internally tracked volume (the `liquid_volume` setting) exceeds this value, the automation will stop. This is a safety feature to prevent overflow.
105111
- `max_subdose`: the maximum volume to add in a single dose. If the volume to add is greater than this value, the volume will be divided into smaller doses.
106112

107113

0 commit comments

Comments
 (0)