Developing measurement classes¶
A measurement class describes the domain workflow. It coordinates MGraph, instruments, measurement points, autosave, and evaluation, but contains neither instrument-specific SCPI commands nor Qt widgets.
Derive from Measure¶
from mpylab.env.Measure import Measure
class ExampleMeasurement(Measure):
def __init__(self, SearchPaths=None):
super().__init__(SearchPaths=SearchPaths)
self.raw_data = {}
self.processed_data = {}
Measure provides logging, operator interaction, autosave, instrument
initialization, RF-off, and pickle restoration. New classes should reuse this
infrastructure rather than introduce independent variants.
Measurement workflow¶
A robust workflow follows these steps:
Prepare the dataset and resume information.
Create
MGraphwith name and condition mappings.Create instruments and initialize them through
_init_measurement_devices.Explicitly apply the logical graph context before each frequency-dependent access. Explicit condition evaluation remains sufficient for graphs without a physical controller.
Add only complete measurement points to the result structure.
Call
do_autosaveregularly.Switch RF off and close instruments on a
finallypath.
Use _finalize_measurement_devices for common finalization. Measurement
errors must not bypass this safety path.
Applying an explicit graph context¶
Custom measurement applications should pass frequency, operating mode, and
similar domain values together to MGraph.ApplyContext. This keeps
condition evaluation, frequency setup, physical switching, and state
read-back in one coherent operation:
from mpylab.tools.mgraph import (
GraphStateMismatchError,
MGraph,
TEM_CONDITION_MAP,
)
graph = MGraph(
dotfile,
themap=names,
SearchPaths=search_paths,
condition_map=TEM_CONDITION_MAP,
allow_legacy_condition_context=False,
)
graph.CreateDevices()
graph.Init_Devices()
requested_context = {"frequency": frequency, "mode": "GTEM"}
try:
context_result = graph.ApplyContext(requested_context)
except GraphStateMismatchError as error:
# MGraph has already switched RF off. The application records
# error.mismatches and asks the operator for a decision.
if not operator_explicitly_selected_reapply(error.mismatches):
raise
graph.ReapplyContext()
context_result = graph.ApplyContext(requested_context)
GraphStateMismatchError.mismatches contains the expected and observed
state for each controller, together with status or query errors where
applicable. The application should record this information and present it
neutrally in its CLI or user interface. It must not interpret
instrument-specific relay state; that domain knowledge remains in the
controller driver.
On a mismatch, MGraph has already called graph-wide RFOff. Aborting
is therefore the safe default. Only an explicit operator choice may first
restore the last planned state through ReapplyContext. The application
then applies the originally requested context again. Merely retrying
ApplyContext is deliberately insufficient because that could silently
override the external switching action.
CheckContextState forces an immediate check; PollContextState
rate-limits repeated queries. RFOn_Devices always checks immediately
before enabling RF. Read and NBRead integrate a rate-limited check
into measurement loops. This is not an asynchronous hardware watchdog, but
it detects external intervention at the relevant program boundaries.
The required DOT attributes and driver contract are documented in the DOT reference. The curated MGraph API lists the result and exceptions.
Autosave contract¶
Before the first autosave, store a structured resume instruction:
self.set_autosave_resume(
measurement="example",
method="Measure_Example",
description=description,
)
On resume, the measurement routine must detect existing data and continue at the first incomplete point. Its test therefore verifies call counts and result data, rather than merely checking that the pickle can be read.
Data structure¶
Prefer dataset[frequency] = quantity for frequency-dependent data, or
use a clearly documented equivalent structure. Keep raw data, evaluated
data, and metadata separate. Store references to preparatory measurements
with dataset key and source so reports can present traceability without
recalculating results.
Evaluation¶
Measurement and evaluation are separate methods. This allows an evaluation
algorithm to run again on an after-measure pickle without accessing
hardware. Evaluation does not modify raw data and records the reference
datasets and relevant parameters it used.