Skip to content

Commit 117df46

Browse files
more
1 parent 8bd0ba3 commit 117df46

File tree

13 files changed

+97
-44
lines changed

13 files changed

+97
-44
lines changed

CHANGELOG.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,15 @@
1717
- Calibration protocols are now exposed via API.
1818
- When a Pioreactor model is changed, a (non-blocking) hardware check is performed.
1919
- You can now restart the web server (lighttpd) and the background task queue, Huey, from the UI. Go to Leader -> "Long-running jobs", and see the "web server and queue" line.
20-
- Added spline curve support for calibrations, including OD standards sessions and calibration charts.
21-
- `pio calibrations analyze` now supports `--fit poly|spline` (default: poly). You can use this to refit a dataset to a spline curve.
20+
- Added spline and akima curve support for calibrations, including OD standards sessions and calibration charts.
21+
- `pio calibrations analyze` now supports `--fit poly|spline|akima`. You can use this to refit a dataset to a spline or akima curve.
2222
- Added estimator artifacts alongside calibrations, including OD fusion estimators stored under `storage/estimators` and managed via the calibration session flow. Estimators are a generalized calibration for more complex algorithms. Calibrations will be restricted to 1D models.
2323
- New unit APIs for estimators:
2424
- `/unit_api/estimators/<device>`
2525
- `/unit_api/estimators/<device>/<estimator_name>`
2626
- Faster startup and shutdown of Pioreactor jobs.
2727
- Charts on Experiment Overview now scale with window size.
28+
- New Estimators page in the UI.
2829

2930
#### Breaking changes
3031
- Moved Self-test to the Inventory page. Pioreactors no longer need to be assigned to an experiment to run self-test.
@@ -35,8 +36,8 @@
3536
- OD calibration devices are now per-angle (`od45`, `od90`, `od135`) instead of just `od`. Physically, this changes the calibration directory in `~/.pioreactor/storage/calibrations/od` to `~/.pioreactor/storage/calibrations/{od45,od90,od135}`. Existing `od` calibration files and active calibrations are migrated during the update.
3637
- Self-test no longer creates a stirring calibration.
3738
- OD reading charts in the UI previously had a sensor label next to the unit, ex: `worker01-2`. Now it is the corresponding angle from `config.ini`. Note: only the global `config.ini` is used, not specific `unit_config.ini` files.
38-
- New OD and stirring calibrations are now fit with a spline, and not a polynomial.
39-
- Calibration curve data is now serialized as tagged structs (`poly`/`spline`) instead of raw lists. `curve_type` is removed and existing calibration files are migrated during the update.
39+
- New OD and stirring calibrations are now fit with a akima, and not a polynomial.
40+
- Calibration curve data is now serialized as tagged structs (`poly`/`spline`/`akima`) instead of raw lists. `curve_type` is removed and existing calibration files are migrated during the update.
4041
- Reorganized calibration protocol modules into `core/pioreactor/calibrations/protocols/` and extracted a `registry.py` for protocol registration.
4142
- Removed OD calibration using a single vial.
4243

core/pioreactor/calibrations/protocols/od_fusion_offset.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,10 @@ def _load_estimator_for_worker(worker: str, estimator_name: str) -> structs.ODFu
103103

104104

105105
def _affine_transform_cubic_fit_data(
106-
curve_data: structs.AkimaFitData | structs.SplineFitData,
106+
curve_data: structs.AkimaFitData,
107107
scale_logc: float,
108108
offset_logc: float,
109-
) -> structs.AkimaFitData | structs.SplineFitData:
109+
) -> structs.AkimaFitData:
110110
if scale_logc <= 0:
111111
raise ValueError("Scale must be positive to transform curve data.")
112112

@@ -121,9 +121,7 @@ def _affine_transform_cubic_fit_data(
121121
for coeffs in curve_data.coefficients
122122
]
123123

124-
if isinstance(curve_data, structs.AkimaFitData):
125-
return structs.AkimaFitData(knots=knots, coefficients=coefficients)
126-
return structs.SplineFitData(knots=knots, coefficients=coefficients)
124+
return structs.AkimaFitData(knots=knots, coefficients=coefficients)
127125

128126

129127
def _apply_logc_affine_to_estimator(

core/pioreactor/calibrations/protocols/od_fusion_standards.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -454,10 +454,8 @@ def advance(self, ctx: SessionContext) -> SessionStep | None:
454454
recorded_data=fit.recorded_data,
455455
ir_led_intensity=float(config["od_reading.config"]["ir_led_intensity"]),
456456
angles=list(FUSION_ANGLES),
457-
mu_splines=cast(dict[pt.PdAngle, structs.AkimaFitData | structs.SplineFitData], fit.mu_splines),
458-
sigma_splines_log=cast(
459-
dict[pt.PdAngle, structs.AkimaFitData | structs.SplineFitData], fit.sigma_splines_log
460-
),
457+
mu_splines=fit.mu_splines,
458+
sigma_splines_log=fit.sigma_splines_log,
461459
min_logc=fit.min_logc,
462460
max_logc=fit.max_logc,
463461
sigma_floor=fit.sigma_floor,

core/pioreactor/structs.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -451,8 +451,8 @@ class OD600Calibration(ODCalibration, kw_only=True, tag="od600"):
451451
class ODFusionEstimator(EstimatorBase, kw_only=True, tag="od_fused_estimator"):
452452
ir_led_intensity: float
453453
angles: list[pt.PdAngle]
454-
mu_splines: dict[pt.PdAngle, AkimaFitData | SplineFitData]
455-
sigma_splines_log: dict[pt.PdAngle, AkimaFitData | SplineFitData]
454+
mu_splines: dict[pt.PdAngle, AkimaFitData]
455+
sigma_splines_log: dict[pt.PdAngle, AkimaFitData]
456456
min_logc: float
457457
max_logc: float
458458
sigma_floor: float

core/pioreactor/web/static/asset-manifest.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"files": {
33
"main.css": "/static/static/css/main.9c7a48b7.css",
4-
"main.js": "/static/static/js/main.1e4ef9e0.js",
4+
"main.js": "/static/static/js/main.78b24d79.js",
55
"static/media/pioreactor_cloud.webp": "/static/static/media/pioreactor_cloud.b15b29e435797dc69d76.webp",
66
"static/media/roboto-all-500-normal.woff": "/static/static/media/roboto-all-500-normal.0ab669b7a0d19b178f57.woff",
77
"static/media/roboto-all-700-normal.woff": "/static/static/media/roboto-all-700-normal.a457fde362a540fcadff.woff",
@@ -30,10 +30,10 @@
3030
"static/media/roboto-greek-ext-700-normal.woff2": "/static/static/media/roboto-greek-ext-700-normal.bd9854c751441ccc1a70.woff2",
3131
"index.html": "/static/index.html",
3232
"main.9c7a48b7.css.map": "/static/static/css/main.9c7a48b7.css.map",
33-
"main.1e4ef9e0.js.map": "/static/static/js/main.1e4ef9e0.js.map"
33+
"main.78b24d79.js.map": "/static/static/js/main.78b24d79.js.map"
3434
},
3535
"entrypoints": [
3636
"static/css/main.9c7a48b7.css",
37-
"static/js/main.1e4ef9e0.js"
37+
"static/js/main.78b24d79.js"
3838
]
39-
}
39+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/static/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Pioreactor"/><link rel="apple-touch-icon" href="/static/logo192.png"/><link rel="manifest" href="/static/manifest.json"/><script defer="defer" src="/static/static/js/main.1e4ef9e0.js"></script><link href="/static/static/css/main.9c7a48b7.css" rel="stylesheet"></head><body><div id="root"></div></body></html>
1+
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/static/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Pioreactor"/><link rel="apple-touch-icon" href="/static/logo192.png"/><link rel="manifest" href="/static/manifest.json"/><script defer="defer" src="/static/static/js/main.78b24d79.js"></script><link href="/static/static/css/main.9c7a48b7.css" rel="stylesheet"></head><body><div id="root"></div></body></html>

core/pioreactor/web/static/static/js/main.1e4ef9e0.js renamed to core/pioreactor/web/static/static/js/main.78b24d79.js

Lines changed: 12 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/pioreactor/web/static/static/js/main.1e4ef9e0.js.LICENSE.txt renamed to core/pioreactor/web/static/static/js/main.78b24d79.js.LICENSE.txt

File renamed without changes.

core/pioreactor/web/static/static/js/main.1e4ef9e0.js.map renamed to core/pioreactor/web/static/static/js/main.78b24d79.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/tests/test_od_fusion.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,8 @@ def _build_estimator_from_records(
7777
recorded_data=fit.recorded_data,
7878
ir_led_intensity=80.0,
7979
angles=list(FUSION_ANGLES),
80-
mu_splines=cast(dict[pt.PdAngle, structs.AkimaFitData | structs.SplineFitData], fit.mu_splines),
81-
sigma_splines_log=cast(
82-
dict[pt.PdAngle, structs.AkimaFitData | structs.SplineFitData], fit.sigma_splines_log
83-
),
80+
mu_splines=fit.mu_splines,
81+
sigma_splines_log=fit.sigma_splines_log,
8482
min_logc=fit.min_logc,
8583
max_logc=fit.max_logc,
8684
sigma_floor=fit.sigma_floor,
@@ -156,7 +154,7 @@ def test_fused_od_from_production_estimator() -> None:
156154
- '135'
157155
mu_splines:
158156
'45':
159-
type: spline
157+
type: akima
160158
knots:
161159
- -2.0
162160
- -0.3010299956639812
@@ -191,7 +189,7 @@ def test_fused_od_from_production_estimator() -> None:
191189
- -7.3415352343282985
192190
- 36.554081606382624
193191
'90':
194-
type: spline
192+
type: akima
195193
knots:
196194
- -2.0
197195
- -0.3010299956639812
@@ -226,7 +224,7 @@ def test_fused_od_from_production_estimator() -> None:
226224
- 3.5419541935843966
227225
- -17.63566863139888
228226
'135':
229-
type: spline
227+
type: akima
230228
knots:
231229
- -2.0
232230
- -0.3010299956639812
@@ -262,7 +260,7 @@ def test_fused_od_from_production_estimator() -> None:
262260
- -79.90998614914638
263261
sigma_splines_log:
264262
'45':
265-
type: spline
263+
type: akima
266264
knots:
267265
- -2.0
268266
- 0.04139268515822507
@@ -277,7 +275,7 @@ def test_fused_od_from_production_estimator() -> None:
277275
- 3.9262454859872643e-16
278276
- -2.603566041973169e-16
279277
'90':
280-
type: spline
278+
type: akima
281279
knots:
282280
- -2.0
283281
- 0.04139268515822507
@@ -292,7 +290,7 @@ def test_fused_od_from_production_estimator() -> None:
292290
- 3.9262454859872643e-16
293291
- -2.603566041973169e-16
294292
'135':
295-
type: spline
293+
type: akima
296294
knots:
297295
- -2.0
298296
- 0.04139268515822507

0 commit comments

Comments
 (0)