Skip to content

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.