Interface Contracts

A contract here is a promise plesty-lib makes to the code built on it: what a class or function guarantees, and what a subclass must provide in return. Modules rely on these promises, so they change only with a new version number and a note in the changelog. Each entry below states the promise and links the page that shows how to use it.

Devices

BaseDeviceSyncModel, in plesty.lib.device.base_device_sync. Every device inherits this class. It combines three independent parts, each a separate base class (a mixin):

  • ConfigSystem, the parameters: declared, checked against their type and range (Parameter System);

  • FunctionSystem, the operations: declared in code or in a JSON file (Function System);

  • TelemetrySystem, a snapshot of the device’s state (status()) and optional callbacks on every read and write (Data & Metadata Schemas).

A subclass implements connect, disconnect, _write_, _query_, check_errors and check_operatability. In return, write and query check the value, log the call, convert the reply, and report it to the callbacks. A with block connects and disconnects, and claims the instrument for this object while it is open. See Base Device.

doc_model() returns a DeviceDocModel: everything a device declares, as data rather than text. Its parameters are grouped, its operations listed, and the methods every device has (standard_methods) are kept apart from the device’s own. Anything that describes a device, such as generated documentation, the server’s describe reply or a control panel, reads this instead of collecting the information itself. See Base Device.

Solvers, in plesty.lib.solver. A CmdSolver turns a parameter into the command that reads or writes it; an OpSolver turns an operation request into the instrument’s reply. SCPISolver also runs any operation whose whole exchange is one SCPI command and one value, taken from the command field of the operation’s declaration, so such operations need no code. See Command Solver.

CompositeDevice.call, in plesty.lib.device.composite_device. When a call to a device on another computer times out, the client is rebuilt and the call tried again, a limited number of times, before the last TimeoutError is raised. See Resilient remote calls.

Preflight: checking that an instrument is really there before a measurement. A connection’s TrafficManager.preflight(address) returns a Preflight result. A device’s preflight() returns the same result as a plain dictionary without serial numbers, so that its server can send it over the network. A composite’s preflight() returns a Preflight with one part per device, each including what that device’s server reported. On a Preflight, ready says whether everything needed is there, summary() explains what is missing, and to_dict() gives the result without serial numbers, for saving. See Preflight: is the instrument actually there?.

Experiments

Experiment, Plan and the journal, in plesty.lib.experiment. build_plan() returns a Plan of Steps, fixed once the run starts and identified by a fingerprint of its content (a SHA-256 hash). Before any device is touched, run() checks that every step names a public method of the experiment. Each step is recorded in an append-only journal. run(resume=<run id>) skips the steps already recorded and refuses to continue if the plan’s fingerprint has changed. teardown() always runs, however the run ends. See Experiment Framework.

Run control, in plesty.lib.experiment.control. A request written to the run folder’s control.json (pause, resume, cancel, abort, or a note) takes effect at the next boundary between two steps. Only an abort is also checked during a step, every half second, and it interrupts the step. See Asking a running measurement to pause or stop.

Result files, in plesty.lib.data.io. save_result writes the data file first, and its description (ResultDocument, JSON) last. A description on disk therefore means its data is complete. load_document reads a description without loading the data; convert_to_hdf5 packs several results into one HDF5 file. See Data & Metadata Schemas.

Analyzers and reports

Analyzer, in plesty.lib.analyzer. A subclass declares input_schema and output_schema and implements one synchronous analyze(). Calling the analyzer checks the inputs, fills in missing units and descriptions of the outputs from the schema, and stamps every array and table in the outputs with its provenance: the analyzer’s class, its package version, and its settings. An analyzer never imports a device. See Analyzer Framework.

Report, in plesty.lib.report. A report is a list of text, tables and figures. save() writes it as JSON; Report.load() reads it back and to_html() or to_latex() renders it, without importing the analyzer that made it. See Reports.

Viewing

Viz, RunData and Plot, in plesty.lib.monitor. Viz makes the viewer for one experiment. RunData reads everything a run has saved, once, and every plot in the viewer shares it. A plot is a title and a function draw(data) that returns what to draw: Line, Scatter, Image, Scalar or Text. Viewing only reads the run folder, so it cannot disturb the measurement. The older Monitor classes still work. See Viewing a Run.

Shell and panels, in plesty.lib.ui. A Panel is anything that fits in a sub-window; Shell is the main window that docks, floats and tabs them, remembers their layout, and refreshes all of them on one timer. Colours and styles come from packaged files, never from Python code. Only plesty.lib.ui.qt imports Qt. See Shell Framework.

Tests every module runs

Contract pipelines, in plesty.lib.test. Each kind of module has a set of tests that checks it keeps these contracts, without the instrument:

Pipeline

For

Checks

Run by plesty-sdk as gate

DevicePipeline

devices

8 tests: the declarations are valid, every parameter and operation works against a simulated instrument, connecting and disconnecting, identity, errors

d1

ExperimentPipeline

experiments

5 tests: the plan is the same every time, every step names a method, the plan survives saving and loading, the lifecycle methods are asynchronous

e1

AnalyzerPipeline

analyzers

5 tests: the schemas are valid, analyze() matches them, a round trip on generated inputs, provenance is stamped

a1

A gate is one of the checks plesty check, the checking command of plesty-sdk, runs before a module may be published. What a simulated instrument cannot show, such as the exact command format, a flaky connection or two devices sharing one computer, is tested on the real instrument by FieldTestPipeline, over the network by client_field_test, and for shared computers by field_test_concurrency. See Testing.