|
STAR
Cal STAR — firmware, DAQ server, and engine design
|
Functions | |
| Path | sidecar_path (str run_id) |
| dict[str, list[tuple[float, float]]] | load (str run_id) |
| list[dict] | tared_components (str run_id, list[dict] components) |
| np.ndarray | apply (str run_id, str entity, np.ndarray t, np.ndarray v) |
Variables | |
| str | TARED_SUFFIX = ".force_kg_tared" |
| str | GROSS_FIELD = "force_kg" |
Load-cell tares recorded during a run, and the tared series derived from them.
Elodin records ABSOLUTE force, always and forever — `LC<n>_Cal.CH<c>.force_kg` means the same
thing in every run ever archived, and this feature did not change that. A tare is display state:
the backend subtracts it on the way to the browser and appends what it did to
`<run_dir>/lc_tare.jsonl`, so what the operator was looking at stays reconstructible afterwards.
This module replays that record. It exposes the reconstruction as a synthetic component,
`…force_kg_tared`, rather than as a toggle on the real one. A toggle would be a query parameter
threaded through three independent read paths (series_json, long_csv_rows, wide_csv_rows), and
missing one means the exported CSV disagrees with the plot the operator was looking at. As a
component name there is a single choke point in load_series, and series, both CSV shapes and the
download all follow for free.
The sidecar is append-only, one JSON object per line:
{"entity":"LC2_Cal.CH1","uid":4201,"event":"set","offsetKg":20.13,
"adcAtTare":8412331,"setAtMs":...,"appliedAtMs":1757800123456}
`appliedAtMs` is the instant the published stream changed, not when a button was pressed — the
backend writes the line from the same code that changes the subtraction. `event` is "set" (a new
tare), "recal" (a re-fit moved the offset with no operator action) or "clear". A recal line is
load-bearing: ignore it and every reconstruction is wrong from the re-fit onward.
There is no terminal line at session stop, so a tare with no following "clear" was in effect to
the end of the run.
| np.ndarray backend.lc_tare.apply | ( | str | run_id, |
| str | entity, | ||
| np.ndarray | t, | ||
| np.ndarray | v ) |
Subtract the offset that was in effect at each sample time. A step function, not one offset across the whole array: a tare set partway through a run must leave everything before it absolute, or the pre-tare portion of every run reads wrong.
Definition at line 113 of file lc_tare.py.
References load().
| dict[str, list[tuple[float, float]]] backend.lc_tare.load | ( | str | run_id | ) |
entity -> [(applied_at_seconds, offset_kg), ...] ascending.
Missing or malformed → {}. A viewer must never fail to open a run over its metadata, and a
partially-written last line is expected: the file is appended to while the run is live.
Definition at line 53 of file lc_tare.py.
References sidecar_path().
Referenced by apply(), and tared_components().
| Path backend.lc_tare.sidecar_path | ( | str | run_id | ) |
Inside the run dir, beside the DB — not a sibling like <run_id>.toml. That file is a sibling only because it is written before elodin-db creates the directory. This one is written mid-run when the directory certainly exists, and living inside it means the run's own deletion takes it too, with no orphan class to clean up.
Definition at line 43 of file lc_tare.py.
Referenced by load().
| list[dict] backend.lc_tare.tared_components | ( | str | run_id, |
| list[dict] | components ) |
The synthetic component entries to add to an index, one per tared LC channel. Only channels the sidecar actually names get one. Synthesising a tared twin for every load cell would make an untared run indistinguishable from a tared one whose offsets happened to be zero — the toggle would be lying about whether a tare existed.
Definition at line 89 of file lc_tare.py.
References load().
| str backend.lc_tare.GROSS_FIELD = "force_kg" |
Definition at line 40 of file lc_tare.py.
| str backend.lc_tare.TARED_SUFFIX = ".force_kg_tared" |
Definition at line 39 of file lc_tare.py.