Skip to content

Commit 90e1318

Browse files
more about custom models
1 parent 4ddec1a commit 90e1318

File tree

7 files changed

+172
-38
lines changed

7 files changed

+172
-38
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
---
2+
title: Customize your Pioreactor hardware
3+
slug: /developer-guide/custom-hardware
4+
description: Extend or override Pioreactor hardware definitions by layering YAML files that hardware.py reads.
5+
hide_table_of_contents: true
6+
---
7+
8+
Pioreactor's hardware layer is intentionally data-driven. Everything in [`core/pioreactor/hardware.py`](https://github.com/pioreactor/pioreactor/blob/main/core/pioreactor/hardware.py) loads user-editable YAML files from `~/.pioreactor/hardware/` (or the folder pointed to by the `DOT_PIOREACTOR` env var). By editing these files you can rewire pins, add new peripherals, or describe an entirely new bioreactor model without touching the Python code. Pair these configs with [custom bioreactor model definitions](/custom-bioreactor-models) so the UI, safety limits, and wiring stay in sync.
9+
10+
## How the loader works
11+
12+
`hardware.py` deep-merges two directories for each **mod** (subsystem):
13+
14+
1. `~/.pioreactor/hardware/hats/<hat_version>/<mod>.yaml` – physical wiring that ships with a specific HAT revision (`hardware_version_info`).
15+
2. `~/.pioreactor/hardware/models/<model>/<version>/<mod>.yaml` – intent for a particular bioreactor model returned by `get_pioreactor_model()`.
16+
17+
Later layers override earlier ones. Missing files are allowed; missing keys throw `HardwareError`s when helpers such as `get_pwm_to_pin_map()` run.
18+
19+
Common mods defined inside `hardware.py` are:
20+
21+
- `pwm.yaml` (`get_pwm_controller`, `get_heater_pwm_channel`, `get_pwm_to_pin_map`)
22+
- `gpio.yaml` (`get_pcb_led_pin`, `get_hall_sensor_pin`, `get_sda_pin`, `get_scl_pin`)
23+
- `temp.yaml` (`get_temp_address`, used by `is_heating_pcb_present`)
24+
- `adc.yaml` (`get_adc_curriers`, which subsequently powers PD channel helpers)
25+
- `dac.yaml` (`get_dac_address`)
26+
27+
You can add additional mods with any key/value structure—`get_layered_mod_config("my_mod")` will still combine the YAML files.
28+
29+
## Step-by-step: add a custom hardware profile
30+
31+
1. **Create directories** for your HAT and model version.
32+
```bash
33+
mkdir -p ~/.pioreactor/hardware/hats/<hat_version>
34+
mkdir -p ~/.pioreactor/hardware/models/<model_name>/<model_version>
35+
```
36+
Use `pioreactor.version.hardware_version_info` (for hats) and your `pioreactor.models` entry for models.
37+
38+
2. **Describe the wiring** (hat layer). Example `~/.pioreactor/hardware/hats/0.2/pwm.yaml`:
39+
```yaml
40+
controller: hat_mcu
41+
heater_pwm_channel: "5"
42+
pwm_to_pin:
43+
"1": 17
44+
"2": 13
45+
"5": 18
46+
```
47+
These keys map directly to `_load_pwm_cfg()` in `hardware.py`.
48+
49+
3. **Describe the capabilities** (model layer). Suppose you added a new auxiliary photodiode ADC:
50+
```yaml title="~/.pioreactor/hardware/models/my_model/v1.0/adc.yaml"
51+
pd1:
52+
driver: ADS1115
53+
address: 0x48
54+
channel: 0
55+
aux:
56+
driver: pico
57+
address: 0x40
58+
channel: 0
59+
salty:
60+
driver: ADS1115
61+
address: 0x49
62+
channel: 2
63+
```
64+
`get_adc_curriers()` will automatically expose `.keys()` for every entry (`pd1`, `aux`, `salty`). Downstream helpers, like `get_available_pd_channels()`, treat `pd*` names as photodiode channels.
65+
66+
4. **Reference new mods in code**. Anywhere in your plugin/automation you can import:
67+
```python
68+
from pioreactor.hardware import get_layered_mod_config
69+
70+
stir_cfg = get_layered_mod_config("stirrer") # merges hats/<hat>/stirrer.yaml and models/<model>/stirrer.yaml
71+
if stir_cfg.get("controller") == "pico":
72+
...
73+
```
74+
This keeps custom hardware logic outside Pioreactor core.
75+
76+
## Tips for customization
77+
78+
- Use integers for all addresses and pins; `hardware.py` casts everything via `int()` and will raise if parsing fails.
79+
- Keep YAML minimal—only override keys that differ from the hat defaults to take advantage of deep-merge layering.
80+
- The helper predicates (`is_ADC_present`, `is_heating_pcb_present`, etc.) are safe ways to gate optional hardware in your jobs.
81+
- Store supporting scripts, cad files, or calibration notes under `~/.pioreactor/hardware/<...>/README.md` so teammates know how to reproduce the wiring.
82+
83+
Once you describe the hardware this way, the rest of the stack—jobs, automations, plugins—just asks `hardware.py` for the capabilities it needs, so new hardware becomes a configuration exercise instead of a fork of the core codebase.
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
---
2+
title: Custom bioreactor models
3+
slug: /custom-bioreactor-models
4+
hide_table_of_contents: true
5+
---
6+
7+
:::tip
8+
This feature is actively under development - let us know what else you would like to see!
9+
:::
10+
11+
If you are building a novel bioreactor on top of our software, you can use the `~/.pioreactor/models` dir to add your own bioreactors. This metadata flows into the Inventory UI, safety interlocks, analytics, and can be consumed from Python via `pioreactor.whoami.get_pioreactor_model()`.
12+
13+
## Directory layout
14+
15+
1. Create the models folder if it does not exist:
16+
```bash
17+
mkdir -p ~/.pioreactor/models
18+
```
19+
2. Add one YAML file per model+version, for example `~/.pioreactor/models/custom_100ml__v1_0.yaml`.
20+
3. Restart the Pioreactor UI to pick up the new definition.
21+
4. Assign pioreactors to this new model on the Inventory UI page or via `pio workers update-model ...` tool.
22+
23+
## Required fields
24+
25+
Each YAML is validated against `pioreactor.structs.Model`, so include at least:
26+
27+
- `model_name`: slug-style identifier (`custom_100ml`).
28+
- `model_version`: semantic-ish version (`"1.0"`).
29+
- `display_name`: friendly label shown in the Inventory.
30+
- `reactor_capacity_ml`: physical vessel size.
31+
- `reactor_max_fill_volume_ml`: operational maximum before spilling.
32+
- `reactor_diameter_mm`: used by stirring + growth-rate heuristics.
33+
- `max_temp_to_reduce_heating`, `max_temp_to_disable_heating`, `max_temp_to_shutdown`: temperature safety thresholds in °C.
34+
35+
## Example definition
36+
37+
```yaml title="~/.pioreactor/models/custom_100ml.yaml"
38+
model_name: custom_100ml
39+
model_version: "1.0"
40+
display_name: "Custom 100 mL, v1.0"
41+
reactor_capacity_ml: 100.0
42+
reactor_max_fill_volume_ml: 95.0
43+
reactor_diameter_mm: 50.0
44+
max_temp_to_reduce_heating: 80.0
45+
max_temp_to_disable_heating: 85.0
46+
max_temp_to_shutdown: 90.0
47+
```
48+
49+
After saving the file, the Inventory page will list “Custom 100 mL, v1.0” in each unit’s model dropdown. The same data becomes available to jobs and plugins:
50+
51+
```python
52+
from pioreactor.whoami import get_pioreactor_model
53+
54+
model = get_pioreactor_model()
55+
print(model.display_name)
56+
print(model.reactor_capacity_ml)
57+
```
58+
59+
## Coordinating with hardware profiles
60+
61+
Model definitions describe intent (volumes, limits), while the hardware loader handles wiring, pin assignments, and sensor addresses. When you introduce a new model, you usually need a matching directory under `~/.pioreactor/hardware/models/<model_name>/<model_version>/` so [`hardware.py` can layer the right YAMLs](/developer-guide/custom-hardware). Keeping the names and versions identical lets software map UI selections → hardware capabilities.
62+
63+
If you are basing your custom model off an existing Pioreactor model, can reuse the hardware for our Pioreactor models:
64+
65+
```
66+
mkdir -p ~/.pioreactor/hardware/models/<model_name>/<model_version>
67+
cp ~/.pioreactor/hardware/models/pioreactor_40ml/1.5/* ~/.pioreactor/hardware/models/<model_name>/<model_version>
68+
69+
```
70+
71+
## Validation and troubleshooting
72+
73+
- Run `python -m pioreactor.models` to ensure your YAML parses; validation errors are also logged via the `models` logger.
74+
- If a model is missing from the dropdown, confirm the filename ends with `.yaml`/`.yml`, the process has read permissions, and the Pioreactor services have restarted.
75+
- Treat this directory like code: commit the YAMLs to version control alongside any CAD notes or lab SOPs so teammates understand the assumptions behind each model.

developer-guide/11-custom_models.md

Lines changed: 0 additions & 28 deletions
This file was deleted.
-46.7 KB
Loading
-38.3 KB
Loading
-17.4 KB
Loading

user-guide/03-Extending your Pioreactor/01-cluster-management/03-backup-and-restore-system-files.md

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,17 @@ description: Export and import a Pioreactor’s ~/.pioreactor directory from the
66
hide_table_of_contents: true
77
---
88

9-
Each Pioreactor keeps its configuration, calibration data, and persistent state inside `~/.pioreactor`. The Inventory page now lets you export that directory as a zip for safekeeping and import it onto the same unit when you need to restore or clone a setup.
9+
Each Pioreactor keeps its configuration, calibration data, and persistent state inside `~/.pioreactor`. The Inventory page now lets you export that directory as a system archive (`.zip`) for safekeeping and import it onto the same unit when you need to restore or clone a setup.
1010

11-
![Manage Pioreactor menu showing export and import actions highlighted](/img/user-guide/inventory-export-import-menu.png)
11+
![Manage Pioreactor menu showing Export system archive and Import system archive actions highlighted](/img/user-guide/inventory-export-import-menu.png)
1212

13-
## Exporting system files
13+
## Exporting a system archive
1414

15-
1. Open the **Inventory** page, find the Pioreactor you want to back up, and click **Manage Pioreactor → Export system files**.
16-
2. Confirm the export when prompted. The UI downloads a file named `<pioreactor>_dot_pioreactor.zip`.
15+
1. Open the **Inventory** page, find the Pioreactor you want to back up, and click **Manage Pioreactor → Export system archive**.
16+
2. Review the dialog and click **Export** when ready. The UI downloads a file named `<pioreactor>_dot_pioreactor.zip`.
1717
3. Store the archive somewhere safe. It contains every file from that unit’s `~/.pioreactor` plus a `pioreactor_export_metadata.json` descriptor (hostname, version, export time).
1818

19-
![Export system files confirmation dialog with the export button highlighted](/img/user-guide/inventory-export-dialog.png)
19+
![Export system archive confirmation dialog with the Export button highlighted](/img/user-guide/inventory-export-dialog.png)
2020

2121
After you confirm, the browser saves a zip named `<pioreactor>_dot_pioreactor.zip`.
2222

@@ -25,15 +25,19 @@ After you confirm, the browser saves a zip named `<pioreactor>_dot_pioreactor.zi
2525
- Since the export is over http, you may need to "approve" your browser to download it (check the download tab in your browser).
2626
- For the leader Pioreactor, it's also exporting the sqlite database. This might take a while for very large databases.
2727

28-
## Importing system files
28+
## Importing a system archive
2929

3030
Use imports when you need to restore a backup, duplicate a Pioreactor after replacing hardware, or bring back calibration data after re-flashing an SD card.
3131

32-
1. On the **Inventory** page, choose **Manage Pioreactor → Import system files**.
33-
2. Read the warning and confirm. You will be prompted to select a `.zip` generated by the export flow.
32+
1. On the **Inventory** page, choose **Manage Pioreactor → Import system archive**.
33+
2. Read the warning and click **Select system archive file**, then pick a `.zip` generated by the export flow.
3434
3. Wait for confirmation in the snackbar. The UI shows a spinner while uploading and tells you when the Pioreactor begins rebooting.
3535

36-
![Import system files confirmation dialog with the import button highlighted](/img/user-guide/inventory-import-dialog.png)
36+
:::danger Important
37+
Importing wipes the existing `~/.pioreactor` on that unit before restoring the archive, so anything not inside the uploaded zip is permanently removed.
38+
:::
39+
40+
![Import system archive confirmation dialog with the Select system archive file button highlighted](/img/user-guide/inventory-import-dialog.png)
3741

3842
Important behaviour to note:
3943

0 commit comments

Comments
 (0)