Skip to content

Commit ff3a0d5

Browse files
some small updateS
1 parent 5c55494 commit ff3a0d5

File tree

5 files changed

+12
-53
lines changed

5 files changed

+12
-53
lines changed

core/pioreactor/background_jobs/od_reading.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,9 +1127,6 @@ def __init__(
11271127
else:
11281128
self.estimator_transformer = estimator_transformer # type: ignore
11291129

1130-
if self.estimator_transformer.estimator is not None:
1131-
self.add_to_published_settings("od_fused", {"datatype": "ODFused", "settable": False})
1132-
11331130
self.adc_reader.add_external_logger(self.logger)
11341131
self.calibration_transformer.add_external_logger(self.logger)
11351132
self.ir_led_reference_transformer.add_external_logger(self.logger)

core/pioreactor/calibrations/protocols/README.md

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -14,42 +14,10 @@ the saved artifact differs.
1414

1515
## How protocols produce artifacts
1616

17-
Protocols define a step registry and are executed through a `CalibrationSession`. During the flow,
18-
protocol steps call one of:
19-
20-
- `ctx.store_calibration(...)` to persist a calibration artifact, or
21-
- `ctx.store_estimator(...)` to persist an estimator artifact.
22-
23-
Both run through the same session engine and UI, but they store into different backends and are
24-
surfaced differently:
2517

2618
- Calibrations are saved under `.../storage/calibrations/` and are listed in calibration APIs/CLI.
2719
- Estimators are saved under `.../storage/estimators/` and are not listed in calibration APIs/CLI.
2820

29-
## Field builders
30-
31-
Protocol steps build forms using `fields.*` helpers from `session_flow.py`. These correspond to
32-
`SessionInputs.*` accessors used in `advance()` methods.
33-
34-
- `fields.str(name, label=None, default=None)` -> `ctx.inputs.str(name, default=..., required=...)`
35-
- `field_type`: `string`
36-
- Use for names, labels, and free-form text.
37-
- `fields.float(name, label=None, minimum=None, maximum=None, default=None)` -> `ctx.inputs.float(...)`
38-
- `field_type`: `float`
39-
- Enforces numeric bounds when provided.
40-
- `fields.int(name, label=None, minimum=None, maximum=None, default=None)` -> `ctx.inputs.int(...)`
41-
- `field_type`: `int`
42-
- Enforces integer bounds when provided.
43-
- `fields.choice(name, options, label=None, default=None)` -> `ctx.inputs.choice(...)`
44-
- `field_type`: `choice`
45-
- Validates input against the provided options.
46-
- `fields.bool(name, label=None, default=None)` -> `ctx.inputs.bool(...)`
47-
- `field_type`: `bool`
48-
- Accepts true/false and common yes/no string inputs.
49-
- `fields.float_list(name, label=None, default=None)` -> `ctx.inputs.float_list(...)`
50-
- `field_type`: `float_list`
51-
- Accepts a list of numbers or a comma-separated string.
52-
5321
## Example
5422

5523
The `od_fusion_standards` protocol uses the calibration session UI, but saves an estimator:

core/pioreactor/cli/calibrations.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ def run_calibration(ctx, device: str, protocol_name: str | None, y: bool) -> Non
103103
raise click.Abort()
104104
protocols_sorted = sorted(
105105
protocols_by_device.values(),
106-
key=lambda protocol: (getattr(protocol, "priority", 99), protocol.protocol_name),
106+
key=lambda protocol: protocol.priority,
107107
)
108108
protocol_names_sorted = [protocol.protocol_name for protocol in protocols_sorted]
109109
if len(protocol_names_sorted) == 1:
@@ -192,10 +192,7 @@ def list_protocols() -> None:
192192
List available protocols for device calibrations.
193193
"""
194194
for device, protocols in get_calibration_protocols().items():
195-
sorted_protocols = sorted(
196-
protocols.values(),
197-
key=lambda protocol: (getattr(protocol, "priority", 99), protocol.protocol_name),
198-
)
195+
sorted_protocols = sorted(protocols.values(), key=lambda protocol: protocol.priority)
199196
protocol_names = [protocol.protocol_name for protocol in sorted_protocols]
200197
click.echo(f"{bold(device)}: {', '.join(protocol_names)}")
201198

@@ -211,7 +208,7 @@ def display_calibration(device: str, calibration_name: str) -> None:
211208
data = load_calibration(device, calibration_name)
212209
except (FileNotFoundError, ValidationError) as exc:
213210
click.echo(f"Error: {exc}", err=True)
214-
raise SystemExit(1) from exc
211+
raise click.Abort()
215212

216213
click.echo()
217214
curve = curve_to_callable(data.curve_data_)

core/pioreactor/cli/estimators.py

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,7 @@ def list_protocols() -> None:
9292
protocols = get_calibration_protocols().get(device, {})
9393
if not protocols:
9494
continue
95-
sorted_protocols = sorted(
96-
protocols.values(),
97-
key=lambda protocol: (getattr(protocol, "priority", 99), protocol.protocol_name),
98-
)
95+
sorted_protocols = sorted(protocols.values(), key=lambda protocol: protocol.priority)
9996
protocol_names = [protocol.protocol_name for protocol in sorted_protocols]
10097
click.echo(f"{bold(device)}: {', '.join(protocol_names)}")
10198
shown = True
@@ -210,26 +207,26 @@ def analyze_estimator(device: str, estimator_name: str, fit: str) -> None:
210207
target_file = ESTIMATOR_PATH / device / f"{estimator_name}.yaml"
211208
if not target_file.exists():
212209
click.echo(f"No such estimator file: {target_file}", err=True)
213-
raise SystemExit(1)
210+
raise click.Abort()
214211

215212
try:
216213
estimator = load_estimator(device, estimator_name)
217214
except Exception as exc:
218215
click.echo(f"Unable to load estimator: {exc}", err=True)
219-
raise SystemExit(1) from exc
216+
raise click.Abort()
220217

221218
if not isinstance(estimator, structs.ODFusionEstimator):
222219
click.echo("Only od_fused estimators are supported for analyze.", err=True)
223-
raise SystemExit(1)
220+
raise click.Abort()
224221

225222
if fit != "akima":
226223
click.echo("Only akima fits are supported for od_fused estimators.", err=True)
227-
raise SystemExit(1)
224+
raise click.Abort()
228225

229226
by_angle = _extract_fusion_by_angle_records(estimator)
230227
if not by_angle:
231228
click.echo("No recorded fusion data available to analyze.", err=True)
232-
raise SystemExit(1)
229+
raise click.Abort()
233230

234231
click.echo(f"Estimator: {estimator.estimator_name}")
235232
click.echo(f"Device: {device}")
@@ -257,15 +254,15 @@ def analyze_estimator(device: str, estimator_name: str, fit: str) -> None:
257254
mu_rmse = _rmse_for_fit(mu_curve, x_vals, y_vals)
258255
except Exception as exc:
259256
click.echo(f"{angle}°: unable to fit mu curve: {exc}", err=True)
260-
raise SystemExit(1) from exc
257+
raise click.Abort()
261258

262259
sigma_reference = [akima_eval(estimator.sigma_splines_log[angle], float(x_val)) for x_val in x_vals]
263260
try:
264261
sigma_curve = _fit_curve_data_from_points(fit=fit, x=x_vals, y=sigma_reference)
265262
sigma_rmse = _rmse_for_fit(sigma_curve, x_vals, sigma_reference)
266263
except Exception as exc:
267264
click.echo(f"{angle}°: unable to fit sigma curve: {exc}", err=True)
268-
raise SystemExit(1) from exc
265+
raise click.Abort()
269266

270267
click.echo(f"{angle}° mu: {curve_to_functional_form(mu_curve)}")
271268
click.echo(f"{angle}° mu rmse: {mu_rmse:0.4f}")

core/pioreactor/web/unit_api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ def _build_calibration_protocol_payloads() -> list[dict[str, Any]]:
132132
title = getattr(protocol, "title", "") or f"{protocol_name.replace('_', ' ').title()} calibration"
133133
description = getattr(protocol, "description", "")
134134
requirements = list(getattr(protocol, "requirements", ()))
135-
priority = int(getattr(protocol, "priority", 99))
135+
priority = int(protocol.priority)
136136
protocols.append(
137137
{
138138
"id": f"{device}_{protocol_name}",

0 commit comments

Comments
 (0)