Simulation
plesty.lib.sim provides stand-ins for hardware, so a contract can be proven
without an instrument on the bench. Three of them, at three different depths.
Class |
Stands in for |
Depth |
|---|---|---|
|
the values an instrument would return |
a schema |
|
a whole device module |
a device class |
|
a Thorlabs APT controller |
a serial port |
None of these belong in a hub module’s shipped code — they are what its tests and the contract pipelines build on.
DataGenerator — Values From a Schema
DataGenerator(seed=None) reads a parameter’s own metadata — dtype, range,
options, shape, headers — and produces a representative random value that
satisfies it. This is what lets the mock gates exercise every registered key
and operation without knowing anything about the device.
from plesty.lib.sim.data_generator import DataGenerator
gen = DataGenerator(seed=42)
value = gen.rand_default(param) # respects dtype, range and options
Beyond rand_default it offers rand_int, rand_float, rand_bool,
rand_str, rand_list, rand_tuple, rand_dict, rand_plesty_array and
rand_plesty_table2d. Pass seed to make a failing run reproducible — the
test helpers thread their own seed argument down to it for exactly that
reason.
Used by device_param_system, device_func_system, DevicePipeline and
FieldTestPipeline. See Test helpers.
DemoDevice — One of Everything
DemoDevice is a complete device that needs no instrument. It answers from an
in-memory store, and its schema is deliberately one of everything the parameter
system has to handle: a plain float and int, a str with options, a
bool, a read-only key, a write-only key, and a grouped key (MOTOR.position)
to exercise full-key resolution. Two operations, measure_power and reset,
cover the acquire and lifecycle sides of the function system.
from plesty.lib.sim.demo_device import DemoDevice, MOCK_ADDRESS
device = DemoDevice(MOCK_ADDRESS) # "mock" — the in-memory store
It exists so tests stop hand-writing their own. Before it, plesty-lib’s tests
had a _MockDevice and plesty-sdk’s scaffold tests had a _DocDevice, each
slightly different and each drifting from the standard separately.
DocDevice remains as an alias of DemoDevice for that older name.
Any address other than "mock" is taken to be a real instrument and refuses
to connect — which is what a module does when the hardware is not there, and
makes the failure path testable too. device_id is generated when omitted, so
constructing the device repeatedly (as the gates do) does not collide on the
resource registry.
DemoDevice is what the spawned mode of
client_field_test
serves, which is how that tier runs in CI at all.
AptMotorSimulator — A Fake Serial Port
AptMotorSimulator is not a device; it is a transport. It presents the
serial-port surface AptTrafficManager expects — write, read, in_waiting,
reset_input_buffer, flush, close — and answers real APT protocol frames,
tracking position, homed and channel as a controller would.
from plesty.lib.sim.apt import AptMotorSimulator
from my_stage import MyRotationStage
stage = MyRotationStage(port="sim", transport=AptMotorSimulator())
stage.connect()
stage.home()
Because it substitutes at the port, everything above it is the real code path:
the framing, the traffic manager, BaseAptDevice, the parameter system. Only
the motor is missing. See
Traffic manager and
Base device.