meas layer#
Common components of meas (measurement) layer are implemented in mahos.meas package. The nodes in the meas layer provide the core functionality of measurement automation. To keep flexibility, there is almost no restriction on node implementation.
However, meas nodes are advised to have explicit state, i.e., to publish topic status (Status type) having state attribute (State type).
If the node has state, we can use StateManager for the state management.
BasicMeasNode#
BasicMeasNode can be used as a base class to implement basic measurement nodes.
This class assumes state of type BinaryState and status of type BinaryStatus.
It also provides additional data management features like fitting and data buffering.
Tweaker#
Tweaker is a generic node for manual tuning of instrument parameters.
This is useful for relatively “floating” instruments that are not directly tied to a specific measurement protocol,
but its state affects the sample / DUT and measurement result.
Examples: programmable (variable gain) amplifiers for the sensors, thermostats, or power supply for electromagnet.
The instrument should have Dynamic interface using ParamDict to be managed by the Tweaker.
Thus, it should implement get_param_dict_labels(), get_param_dict(), and configure().
The start(), stop(), and reset() methods can also be invoked from Tweaker.
Some measurement nodes can take tweakers: list[str] in the configuration target.
By doing so, the status of Tweaker(s) can be embedded in the measurement data.
See also Tutorial 3: Manual Operation for an example with mock instrument.
PosTweaker#
PosTweaker is a generic node for manual tuning of positioner instruments.
Its role is similar to Tweaker,
but PosTweaker has dedicated interface and GUI for positioners.
PosTweaker can also be listed in tweakers: list[str] in the target configuration of measurement nodes.
See also Tutorial 3: Manual Operation for an example with mock instrument.
Recorder#
Recorder is a generic node for recording time-series data from instruments.
To use Recorder, an instrument must implement the following APIs: get_param_dict_labels(), get_param_dict(), configure(), start(), stop(), and get().
If a channel unit is not given in the mode configuration, get("unit") is additionally required.
Recorder uses selected mode ([...recorder.mode.<label>]) as a map from Recorder channel name
to instrument channel configuration. For each channel config:
inst: instrument name on target server.label: passed to instrument calls aslabel=...(defaults to"").key: key for acquisition callget(inst, key, label=label)(defaults to"data").unit: fixed unit string stored in data; if omitted, Recorder queriesget(inst, "unit", label=label).
Main API-call flow is:
On parameter query, Recorder calls
get_param_dict(inst, label)per channel.On start, Recorder optionally locks instruments, calls
configure(inst, params[channel], label), resolves unit (configunitorget("unit")), then callsstart(inst, label).In ACTIVE state, Recorder polls each channel by
get(inst, key, label)and appends values to time-series data under the Recorder channel name.On stop, Recorder calls
stop(inst, label)and releases locks.On reset (IDLE only), Recorder calls
reset(inst, label)without lock/release handling.
See also Tutorial 3: Manual Operation for an example with mock instrument.
Sweeper#
Sweeper is a generic 1D sweep measurement node.
It controls one sweep parameter and samples one measurement value at each sweep point.
The worker repeats the line sweep for the requested number of times and stores the result in
SweeperData.
The sweep condition can be configured by start, stop, num, log, and delay
parameters. sweeps controls the number of repeated sweeps (0 means infinite).
Configuration sections x and measure define instrument names and API keys used
for set/get operations.
The x instrument must support set and measure instrument must support get.
The runtime loop is set(x) -> delay -> get(measure) at each point.
Sweeper intentionally does not call instrument get_param_dict(), configure(),
start(), or stop(). If your instrument needs these APIs, invoke them manually
via Tweaker, scripts, or interactive sessions before running Sweeper.
GridSweeper#
GridSweeper is a generic 2D planar sweep node.
It controls two sweep parameters (x and y axes) and samples one measurement value on each
grid point. One completed y-loop corresponds to one 2D image, and repeated images are stacked
in GridSweeperData.
Both axes support start, stop, num, log, and delay parameters.
sweeps controls the number of repeated 2D images (0 means infinite).
Configuration sections x, y, and measure define instrument names and API keys used
for set/get operations.
The x and y instruments must support set and measure instrument must support get.
The runtime loop is nested set(y) -> delay_y -> set(x) -> delay_x -> get(measure)
across the configured grid.
GridSweeper intentionally does not call instrument get_param_dict(), configure(),
start(), or stop(). If your instrument needs these APIs, invoke them manually
via Tweaker, scripts, or interactive sessions before running GridSweeper.
StateManager#
StateManager is used as a manager of meas node states.
It subscribes to topic states of all the managed nodes.
We can register the command for the manager, which is a map from nodes to required states.
Example configuration looks like below.
[localhost.manager1.node]
"localhost::node1" = ["mahos.msgs.common_msgs", "BinaryState"]
"localhost::node2" = ["mahos.msgs.common_msgs", "BinaryState"]
[localhost.manager1.command]
all_idle = { "localhost::node1" = "IDLE" , "localhost::node2" = "IDLE" }
This manager manages node1 and node2, both of which have BinaryState.
A command named all_idle is a request to set both nodes to the IDLE state.
Before a command is executed, the nodes’ states (last_state) are stored.
After a command, we can use restore request to recover the last_state.
The figure below explains the command and restore operations.
Command and Restore operations of StateManager#
The manager1 is configured as the config snippets above.
(a): In the initial state, node1 is ACTIVE and node2 is IDLE.
(b): node3 requests the manager1 to restore from all_idle command (Restore(all_idle)), which fails as the last_state is empty (all_idle has never been executed).
(c): node3 requests all_idle command execution (Command(all_idle)), which turns both node1 and node2 to IDLE states. Here, last_state is stored.
(d): node3 requests restore again (Restore(all_idle)). It succeeds this time and last_state is restored (node1 becomes ACTIVE).