Skip to content

Commit b0d85c7

Browse files
docs
1 parent d40be12 commit b0d85c7

File tree

5 files changed

+168
-3
lines changed

5 files changed

+168
-3
lines changed

static/img/user-guide/gr.png

53.9 KB
Loading

static/img/user-guide/nod.png

43.8 KB
Loading

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@ To further avoid overflow, we limit how much liquid is added in a single pump cy
9595
### Volume parameters
9696

9797

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.
98+
- **Initial liquid volume**: this is how much liquid is initially in the vial
99+
- **Max liquid volume**: the efflux tube's position determines the maximum volume your liquid volume will reach.
100100

101101

102102
### Configuration parameters
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
---
2+
title: Growth rate cuve modelling
3+
slug: /growth-rate-modelling
4+
---
5+
6+
7+
## Introduction to our growth-rate model
8+
9+
10+
> The study of the growth of bacterial cultures
11+
does not constitute a specialized subject or branch
12+
of research: it is the basic method of microbiology.”
13+
Monitoring and controlling the specific growth rate
14+
should not constitute a specialized subject or branch
15+
of research: it should be the basic method of advanced
16+
microbial bioprocessing.
17+
> \- Jacques Monod
18+
19+
The first step to controlling a culture's growth is to measure it. To do this, we need to model the rate of growth. We've seen other attempts at modelling the growth rate, but they all assumed too much:
20+
21+
- Exponential growth model: perhaps truly early on, but certainly not the case near stationary.
22+
- Logistic growth model: requires an assumption about the max optical density, and assumes symmetric growth around the inflection point.
23+
- Gompertz models and other models: more parameters, less interpretable, and still make strong assumptions about the trajectory of growth.
24+
25+
Further more, none of these can model a culture in a turbidostat or chemostat mode, where the optical density is dropping quickly during a dilution, but the growth rate should remain constant.
26+
27+
### Re-visiting a growth model
28+
29+
We are often introduced to a growth model by the simple exponential growth model:
30+
31+
$\text{OD}(t) = \exp{\left( \text{gr} t \right)}$
32+
33+
Plainly put, the culture grows exponentially at rate $\text{gr}$. Like we mentioned above, this might be true for small time-scales, but certainly over the entire lag, log, and then stationary phases, this is not the case.
34+
35+
There's a hint of an interesting idea in the last paragraph though: _"over small time scales"_. What if we cut up the growth curve into many small time intervals, and computed a growth rate for each interval? Then our growth rate can be changing: starts near 0 in the lag phase, can increase to a peak in the log phase, and then drop to 0 again in the stationary phase. We also don't need to assume any parametric form for the growth rate, we can just measure it directly from the data.
36+
37+
Our new formula might look like:
38+
39+
40+
$$\text{OD}(t) = \exp{\left(\text{gr}_0 \Delta t + \text{gr}_1 \Delta t + ... \right)}$$
41+
42+
If we think more about this, and we keep shrinking our time interval towards zero, this is just an integral:
43+
44+
$$
45+
\text{nOD}(t) = \exp{ \left( \int_0^t \text{gr}(s)ds \right)}
46+
$$
47+
48+
There's still no particular assumption about the shape of the growth rate function, $gr(s)$. For example, consider the following ODs from a batch experiment:
49+
50+
![](/img/user-guide/nod.png)
51+
52+
Using our estimation technique outlined below, we can estimate the growth curve as:
53+
54+
![](/img/user-guide/gr.png)
55+
56+
57+
We can see that the growth is very dynamic, and certainly not a single number or a constrained form!
58+
59+
60+
### Estimating a non-parametric growth rate
61+
62+
A non-parametric, dynamic growth rate sounds great, but we've replaced a estimation of a single value (or handle of values) to an entire function! This seems expensive!
63+
64+
Luckily, we do the work for you. We will compute $gr(t)$ using a statistical algorithm, **the Kalman filter**. The Kalman filter is an algorithm that estimates the state of a dynamic system from noisy measurements. In our case, the state is the growth rate, and the measurements are the optical density readings. We input optical density observations one at a time, and the Kalman filter updates its estimate of the growth rate based on the new observation. This allows us to track the growth rate in real-time, as the culture grows.
65+
66+
### Online: Using the Pioreactor's software
67+
68+
When you start the "Growth rate" action in your Pioreactor, the action starts reading from the stream of OD readings, and computes the growth-rate for each reading. The growth rate is then displayed in the Pioreactor UI.
69+
70+
### Offline: Using the [growth-rate tool](https://growth.pioreactor.com)
71+
72+
We have implemented our algorithm and estimation in an easy-to-use web app, the [growth-rate tool](https://growth.pioreactor.com). You can use this tool to upload your optical density and (optionally) dosing events data, and it will compute the growth rate for you.
73+
74+
### Backed by our Python library, `grpredict`
75+
76+
If you want more control, you can use our `grpredict` Python library, available with:
77+
```
78+
pip install grpredict
79+
```
80+
81+
This is the same library that's used in our Pioreactor software.
82+
83+
### Model parameters
84+
85+
- **baseline samples**: the number of samples at the start of the dataset to use for initial variance calculations, and as the baseline value to normalize the optical densities against (so that the initial nOD is nearly equal to 1.0)
86+
- **Growth-rate std**: a Kalman-filter specific parameter. Higher values allow more flexibility in the growth rate, lower values smooth the growth rate.
87+
- **nOD std.**: a Kalman-filter specific parameter. If your dosing large amounts at a time, you may want to increase this.
88+
- **OD std. factor**: a Kalman-filter specific parameter. If your sample are _very_ noisy, you can increase 2x to dampen the affect of that noise.
89+
- **Outlier threshold**: a Kalman-filter specific parameter. Large outliers or shifts in OD will likely be taken care of by setting this to 5, but try values between 3 and 5 if you want to handle less large outliers.
90+
91+
92+
## Required CSV schemas for growth-rate tool
93+
94+
To upload your optical density and dosing events data to the Pioreactor, you need to prepare CSV files with specific schemas. Below are the required formats for each file, along with common pitfalls to avoid.
95+
96+
:::tip
97+
98+
If using the Pioreactor UI to export datasets, these already have the required schema.
99+
100+
:::
101+
102+
### 1. Optical-Density CSV
103+
104+
| **Column** | **Required?** | **Expected dtype** | **Description** |
105+
| -------------------------------- | ------------- | ------------------ | ------------------------------------------------------------------------------------------------------------- |
106+
| `od_reading` | Yes | **float** | Raw or pre-normalized optical-density measurement. |
107+
| `hours_since_experiment_created` | Yes | **float** | Elapsed hours since the experiment’s “time 0”. Use decimals for sub-hour resolution (e.g. `0.4167` ≈ 25 min). |
108+
109+
:::info
110+
111+
Additional columns (sensor angle, experiment name, etc.) are ignored by the parser, so feel free to keep them—just make sure the two required columns exist and are spelled exactly as above (case-sensitive).
112+
113+
:::
114+
115+
#### Minimal example
116+
117+
```csv
118+
od_reading,hours_since_experiment_created
119+
0.1725,0.397
120+
0.1735,0.399
121+
0.1749,0.402
122+
```
123+
124+
---
125+
126+
### 2. Dosing-events CSV
127+
128+
| **Column** | **Required?** | **Expected dtype** | **Description** |
129+
| -------------------------------- | ------------- | --------------------- | --------------------------------------------------------------------------------------------- |
130+
| `event` | Yes | **category** (string) | Either `add_media`, `add_alt_media`, or `remove_waste`. Other strings are treated as distinct categories. |
131+
| `volume_change_ml` | Yes | **float** | Signed volume change (mL). Convention: positive for **additions**, negative for **removals**. |
132+
| `hours_since_experiment_created` | Yes | **float** | Timestamp in **hours**, exactly matching the OD clock. |
133+
134+
#### Minimal example
135+
136+
```csv
137+
event,volume_change_ml,hours_since_experiment_created
138+
add_media,1.0,1.533
139+
remove_waste,-1.0,1.544
140+
remove_waste,-2.0,1.567
141+
```
142+
143+
---
144+
145+
### Common pitfalls
146+
147+
* **Header spelling matters**`odReading`, `OD_reading`, or trailing spaces will fail validation.
148+
* **Mixed delimiters** – Ensure you’re saving with commas; semicolons require a manual find-&-replace.
149+
* **Units**`volume_change_ml` must be millilitres; convert L → mL beforehand.
150+
* **Consistent clock** – Both files must use the same `hours_since_experiment_created` reference, or dilution jumps won’t align.
151+
152+
---
153+
154+
### Quick checklist before uploading
155+
156+
1. **Open in a plain-text editor** – Verify the first line matches the header tables above.
157+
2. **Scan for blank lines** – Delete empty rows at the end; they sometimes appear after Excel saves.
158+
3. **Check decimals** – European locales may export `0,1725`; switch to `.` decimal point.
159+
4. **Save as UTF-8 CSV** – Most editors do this by default; avoid Excel’s “CSV (Macintosh)” variant.
160+
161+
162+
163+
164+
165+

user-guide/30-Advanced/07-remote-access/03-tailscale.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Tailscale is a really cool service! You may find yourself using it for other pro
1414
1. Sign up for an account at [Tailscale](https://tailscale.com/). The free account is fine for now.
1515
2. Once signed up and logged in, visit the [Tailscale admin](https://login.tailscale.com/admin/machines).
1616
3. Install [Tailscale on your computer](https://tailscale.com/download).
17-
4. [SSH into your leader Pioreactor](/user-guide/accessing-raspberry-pi). Install Tailscale for Raspberry Pi with the following: `curl -fsSL https://tailscale.com/install.sh | sh`. You don't need to install anything on the workers.
17+
4. [SSH into your leader Pioreactor](/user-guide/accessing-raspberry-pi). Install Tailscale for Raspberry Pi with the following: `curl -fsSL https://tailscale.com/install.sh | sh`. Don't miss that you also need to run `sudo tailscale up`. _You don't need to install anything on the workers_.
1818
5. Back in your [Tailscale admin](https://login.tailscale.com/admin/machines), you should see two machines: your computer and the leader Pioreactor. Make note of the ipv4 address for the leader - we will use it below.
1919
6. You should still be able to access `http://pioreactor.local` without any problems.
2020
8. 1. In your **shared config.ini**, add your ipv4 address to the `[mqtt]` section:

0 commit comments

Comments
 (0)