Components
This page provides details on the main component/entity types that make up a deployment of the LECO.
Director
A Director manages a part of or the entire setup, orchestrating the Components according to the needs of the experiment. It can, among other things,
issue commands to Actors
request data from individual Actors
read data from an Observer
Potentially a GUI could be attached here too.
Actor
An Actor is a component that interfaces with a (hardware) Device and that has a specific API on the LECO side. An Actor must contain a separate Driver object which communicates with the Device.
We define how the other LECO components interact with the Actor, how it determines and announces its capabilities, etc. An Actor implements the mapping between LECO messages and Driver calls/attribute access.
An Actor must contain/manage/provide
An Driver that communicates with the connected Device, including managing its lifecycle (init, operations, shutdown)
The name of the connected instrument
A list of available Parameters (properties/attributes to get/set) and Actions (methods to call)
set
/get
/get_all
/call
interfaces (for incoming commands to use to act on Parameters and Actions)
An Actor may contain/manage
A list of Parameters to poll/publish regularly (and the interval for that)
A cache of parameter values (to avoid unnecessary communication).
If caching is included, the
get*
interfaces must include a configurable cache timeout and a way to force fetching a fresh value.
Concurrent access management/locking
Logging configuration
Driver
The Driver object takes care of communicating with the Device, and is always contained in an Actor.
This object is external to LECO, for example a pymeasure.Instrument
instance or something from another instrument library.
This is the place where all instrument libraries (including pymeasure) wire their hardware interface classes into LECO.
Interfacing with the Driver is the task of instrument-library-specific Actors.
Concerning the LECO, we draw the abstraction boundary at the Driver – the details on how this communicates with a Device (SCPI, dll, …) should not be relevant for the protocol details.
TODO
We might want to add the notion of “Channels”, especially for the multi-Director stuff
Action
An Action represents a method or function of the Driver represented by an Actor. It can be called with zero or more arguments.
Parameter
A Parameter represents a property (in the English, not the Pythonic sense) of the Driver represented by a Actor.
It has a name and can be read(get
) or set
.
Note
Recent values may be cached in the Actor.
It may correspond closely to attributes or Python (or PyMeasure) properties of the Driver. It may have unit information that is used when sending data over the Network.
Procedures
Sequences of steps that make up experiment runs, e.g. PyMeasure procedures. These instructions could be consumed by a Director and trigger a sequence of commands (ramps, loops, conditionals,…).
TODO
This is a placeholder, we have not fleshed out the concept yet
Processor
The processor runs some kind of processing operation on one or more inputs and produces one or more outputs. It can be stateless (e.g. temperature conversion) or stateful (like a PID controller). It may act regularly of its own accord.
The Processor would send commands to an Actor, instructing it to set
/get
/call
a given Parameter/Action by name, with a value if appropriate, and receive replies.
This could look for example like this:
Coordinator
A component primarily tasked with routing/coordinating the message flow between other Components. It represents a zmq broker, proxy or similar entity.
There are several Coordinator variants meant for various tasks. They are using different kind of communication types (zmq socket types) since they have different communication requirements.
Note
The use of a Coordinator avoids the complexity/scaling of a purely point-to-point messaging approach between all Components.
Control Coordinator
A Control Coordinator is concerned with routing control channel messages from/to different Components, using a distributed request-reply communication pattern.
Every network needs at least one Control Coordinator. Every Node must have exactly one Control Coordinator, all other Components within one Node directly exchange messages only with their Node’s Control Coordinator.
Note
Multiple Control Coordinator instances may be necessary for large deployments, but a single coordinator instance should be sufficient for operation.
Data Coordinator
A Data Coordinator is responsible for receiving and publishing data channel messages. It uses a publish-subscribe connection pattern.
Logging Coordinator
A Data Coordinator is responsible for receiving and publishing logging channel messages. Structurally, it is identical to a Data Controller, except that it deals with logging, not data channel messages.
Observer
A Component that receives data from other Components, e.g. for logging, storage, or plotting, either directly in a streaming fashion, batched, or delayed.
It only consumes message streams, but does not command Actors
.
Note
Depending on setup, some commanding might be necessary, e.g. to subscribe/register.
Notes
Complexity scaling
We want to leave the entry threshold as low as possible, the learning curve flat, and the usability of LECO modular. If someone wants to just connect with an Actor instance, that should be possible, and easily understood, as the Actors have a consistent API. This assumes that a library-specific Actor has already been written by the library maintainers.
Once a user is familiar with that, and a slightly bigger system is envisaged by them, multiple Actor classes might be used, maybe with a Processor doing some useful transformations, and a Director attached to them (via Coordinators), so all can be controlled together. Possibly Procedures are added for sequencing, too. Once a user is familiar with this bigger framework, they can then add new Components as needed, to grow their system one by one.
For quick tests, some simple measurements (and the first steps), one can still just open a python interpreter, connect to the hardware with an Actor (containing e.g. a pymeasure.Instrument
Driver), and measure some things using, ideally with out-of-pymeasure’s-box classes for devices, and the only thing one needs to understand for it, is the Actor interface, no need for servers, proxies, brokers, GUI, databases, etc.
This would give users a broad freedom, while at the same time they can be guided step by small step to master bigger challenges and journeys.