A measurement workflow is the core of an experiment. It orchestrates devices, acquires data, and persists results. PLESTY experiments follow a structured pattern to ensure reproducibility and error handling.
Workflow structure
A typical measurement workflow follows these steps:
- Initialize — connect to devices and set initial parameters
- Configure — set device parameters for the measurement
- Acquire — read data from devices
- Process — optionally run analyzers on the data
- Save — persist results
- Cleanup — disconnect devices
Example: Power sweep
class PowerSweep:
"""Measure power output across a range of laser drive currents."""
def __init__(self, composite: CompositeDevice) -> None:
self.composite = composite
self.results = []
def run(self, current_range: list[float]) -> dict:
"""Run a power sweep measurement."""
for current in current_range:
# Configure
self.composite.call("laser", "_write_", key="current", value=current)
# Acquire
power = self.composite.call("meter", "_query_", key="power")
# Save
self.save_result({
"current": current,
"power": power,
})
return {"measurements": self.results}
def save_result(self, data: dict) -> None:
"""Persist a measurement result."""
self.results.append(data)
Result persistence
Use save_result() to persist measurement data. The SDK provides this method for experiment classes. Never use ad-hoc persistence — always use save_result (this is enforced by gate e2).
def save_result(self, data: dict) -> None:
"""Persist a measurement result.
Args:
data: Dictionary of measurement data to save.
"""
...
Error handling
Wrap device calls in try-except blocks to handle communication failures:
def run(self) -> dict:
try:
self.composite.call("laser", "connect")
# ... measurement logic ...
except ConnectionError:
self.composite.reconnect("laser")
# Retry logic
finally:
self.composite.call("laser", "disconnect")
Next steps
- Test your experiment with mock devices
- Learn about experiment gates (e1, e2)