Event handling
When performing measurements or interacting with an instrument, you may want to react to specific occurrences in real-time, such as when a new data point is received or when a measurement starts. PyPalmSens provides an event system via pypalmsens.InstrumentManager.
Events are registered using on_<event_name> methods on the manager (or its async counterpart) and return an EventHandle object. To stop listening to an event, call the .cancel() method on the returned handle.
Using events
The most common use case is to react to data as it arrives during a measurement. This is particularly useful for real-time plotting or monitoring.
import pypalmsens as ps
with ps.connect() as manager:
# Register a callback for new data points
handle = manager.on_curve_new_data(print)
# Start a measurement
manager.measure(ps.CyclicVoltammetry())
# Stop listening to the event
handle.cancel()
Event types
Measurement events
These events allow you to monitor the lifecycle of a measurement:
| Method | Triggered when... | Callback argument |
|---|---|---|
| on_measurement_setup | Before the measurement starts (useful for resource setup) | None |
| on_measurement_begin | At the start of a measurement | Measurement |
| on_measurement_end | After a measurement ends (successfully or due to error) | Measurement |
| on_measurement_teardown | After the measurement ends (useful for cleanup) | None |
For example:
>>> import pypalmsens as ps
>>> def begin_callback(measurement):
... print(f"{measurement.title} started")
>>> def end_callback(measurement):
... print(f"{measurement.title} ended")
>>> with ps.connect() as manager:
... _ = manager.on_measurement_begin(begin_callback)
... _ = manager.on_measurement_end(end_callback)
... measurement = manager.measure(ps.ChronoPotentiometry(run_time=5))
Chronopotentiometry started
Chronopotentiometry ended
Standard measurements
For measurements that produce (multiple) curves like Cyclic Voltammetry or Chronopotentiometry, you can subscribe to events related to individual curves:
| Method | Triggered when... | Callback argument |
|---|---|---|
| on_curve_begin | A new curve starts being recorded | Curve |
| on_curve_new_data | New data points are received (batched) | CallbackData |
| on_curve_end | A curve has finished recording | Curve |
>>> import pypalmsens as ps
>>> import time
>>> def begin_callback(curve):
... print(f"New curve: {curve.title}")
>>> def end_callback(curve):
... print(f"Measured {len(curve)} points")
>>> with ps.connect() as manager:
... _ = manager.on_curve_begin(begin_callback)
... _ = manager.on_curve_end(end_callback)
... measurement = manager.measure(ps.CyclicVoltammetry(n_scans=3))
New curve: CV i vs E Scan 1
Measured 20 points
New curve: CV i vs E Scan 2
Measured 20 points
New curve: CV i vs E Scan 3
Measured 21 points
Impedimetric measurements
Impedance Spectroscopy measurements (EIS/GEIS) use a slightly different set of events:
| Method | Triggered when... | Callback argument |
|---|---|---|
| on_eis_data_begin | A new EIS data set starts being recorded | EISData |
| on_eis_new_data | New EIS data points are received (batched) | CallbackDataEIS |
| on_eis_data_end | An EIS data set has finished recording | None |
Communication and Status events
These events provide insight into the communication layer and instrument state:
| Method | Triggered when... | Callback argument |
|---|---|---|
| on_receive_message | A new message is received from the device | str |
| on_receive_status | The instrument's idle status changes | Status |
| on_error | An error occurs during a measurement | None |
If you use MethodSCRIPT, you can use on_receive_message to listen for messages from send_string.
For example:
>>> import pypalmsens as ps
>>> method = ps.MethodScript(script='send_string "hello world!"')
>>> with ps.connect() as manager:
... _ = manager.on_receive_message(print)
... measurement = manager.measure(method)
Running: MethodSCRIPT Sandbox
hello world!
Async events
For asynchronous workflows, use the corresponding async methods on pypalmsens.InstrumentManagerAsync. The callback signatures remain the same, but you must ensure your callbacks are compatible with an async environment if you are using asyncio.
Note that on_receive_status specifically requires an active event loop to function correctly as it uses thread-safe scheduling to bridge the communication layer and your code.