A run is one measurement made by an experiment module — a folder of
journal, plan, records and analysis files on disk. That folder is complete, but it is not
something you can send a colleague. Since this month, plesty-bench (the program
that manages a lab PC and runs experiments on it) compiles every finished run into a single
report.html: what was run, how it was configured, which instruments took part,
what the analyzers found, and every recorded value.
analysis/*.report.jsonwhat each analyzer says it foundreport.htmlone file, no script, nothing fetchedWhat a report contains
The report reads only what is already in the run folder — it invents nothing. Sections appear when the run has something to put in them:
- Run info — experiment, run id, final state, start and end time, steps done and failed, records committed.
- Bench info — the experiment module and the instruments, as the run recorded them.
- Device setup — for each device: which lab PC ran it, the network address the run reached it on, and where that PC sees the shared data disk. A run that was stopped and resumed lists every start.
- Configuration — the settings frozen into the run's plan when it started, so it is what the run actually used.
- Operator notes — remarks recorded during the run (“helium top-up”), placed between the steps they happened between.
- Analysis — each analyzer's own summary: sentences, tables and figures, with the analyzer's name, version and options.
- Raw data — every committed record, one table per kind of step (up to 500 rows each). A value that is the same in every row is stated once above the table instead of repeated.
Using it
For usersYou get a report without doing anything
When a run ends — completed, stopped or aborted — its job writes report.html
into the run folder. A folder handed on months later explains itself. If the report cannot be
compiled, that is one line in the job log; the run is not marked failed, because the
measurement and its data are already safe on disk.
In the console
On the Experiments tab, select a run and open its Report pane:
| Control | What it does |
|---|---|
| Report line | Names the run's report.html, when it was written and its size — or says when it will have one. |
| Export HTML | Writes a fresh copy of the report wherever you choose, with a file name that says which experiment and run it describes. |
| Add report | Asks What happened? and records your note in the run's journal while the run is going. Notes show up in the report's Operator notes section. Also under Experiment ▸ Report…. |
| Open run | Opens the run folder in your file manager — available while the run is going too, so you can watch files appear. |
plesty-lib's document loaders,
so a bench with an older plesty-lib can still report on a run written by a newer
one.Contributing to it
For developers & contributors1 · Make your analyzer say what it found
The Analysis section is filled from reports, a new part of
plesty-lib (plesty.lib.report). A report is an ordered list of
blocks — text, tables and figures — saved as a <name>.report.json file next
to the analyzer's outputs. Any reader, including the bench, renders it to HTML or LaTeX
without importing your analyzer.
You get a report for free: Analyzer.report(outputs) tabulates every output
whose output_schema entry has "role": "result" (the default). Mark
helper outputs "role": "intermediate" to keep them out, and give entries a
"title". To say more, override it:
from plesty.lib.report import Cell, Figure, Report, Table, Value
from plesty.lib.monitor import Line, Scatter
def report(self, outputs):
return Report(
[
r"Two of four lines split by $\Delta E = 11.5 \pm 0.3$ µeV.",
Table(header=[[Cell("Line"), Cell(r"$\Delta E$ (µeV)")]],
rows=[[Cell("775.012 nm"), Value(11.5, err=0.3)]]),
Figure([Scatter(x=angles, y=centres), Line(x=angles, y=fitted)]),
],
title="Fine structure",
provenance=self.provenance(),
)
Cells accept **bold**, *italic*, `code`
and $math$; Value(x, err=σ) is printed to the precision its uncertainty
allows; rowspan= / colspan= build paper-style headers. Equations become
MathML when plesty-lib is installed with its report extra.
2 · Save the report from your experiment
The experiment module decides where results live. Save the report under the run's
analysis/ folder with the shared suffix, and the bench picks it up — its tables
and figures replace the generic array dump it would otherwise show for those outputs:
from plesty.lib.report import REPORT_SUFFIX
stem = self.run_dir / "analysis" / subject
provenance = {"run": self.run_id, "qd": subject, "analyzer": analyzer.provenance()}
save_result(outputs["fine_structure"], f"{stem}_fine_structure", provenance)
report = analyzer.report(outputs)
report.title = f"Fine structure of {subject}"
report.provenance = provenance # same provenance as the outputs it covers
report.save(f"{stem}{REPORT_SUFFIX}") # → analysis/<subject>.report.json
This is exactly what the plesty-pol-pl experiment does with the
plesty-fss fine-structure analyzer. Give the report the same provenance as
the outputs it describes — that is how the bench knows not to list those outputs twice.
report events
(plesty.lib.experiment.control.report(run_dir, "…")); the device setup comes from
what plesty-lib records when a run starts. A run written by an older
plesty-lib that did not record the setup simply says so in that section.3 · Change how the report looks
Layout and style are assets, not Python strings: the markup is
plesty/server/assets/report.html (named <template data-fragment>
pieces with placeholders) and the style is plesty/server/assets/report.css, whose
colours resolve through plesty-lib's palette tokens and CSS
light-dark(). The compiler is plesty/server/services/run_report.py
(report(), write(), suggested_name()); run values are
always HTML-escaped. Cover a change in tests/test_run_report.py — and keep the rule
that the page carries no script and fetches nothing.