Skip to content

Events and Callbacks#

Terminology confusion!

A quick warning on terminology: the name "event" may refer to two different things in pymmcore-plus, which are not to be confused.

This page discusses the "events" that are emitted by the CMMCorePlus and MDARunner objects. These are occurrences that your program can react to by registering callback functions. These are also known as "signals" in the context of the Qt framework or psygnal.

The term "event" may also used to refer to the useq.MDAEvent objects that are consumed by the Acquisition Engine. These are not the same as the "events" discussed on this page.

Both the CMMCorePlus object and the CMMCorePlus.mda (MDARunner) objects have events attributes that can be used to register callbacks for events that occur as the state of the microscope changes, or as an acquisition sequences progresses.

Event backends#

pymmcore-plus supports both Qt-based and psygnal-based event signaling.

The default behavior is to use Qt-backed signals when a global QApplication instance has been created in the main process, and psygnal otherwise.

If you would like to force a specific event backend, you can do so by setting the MMCORE_PLUS_SIGNALS_BACKEND environment variable to qt, psygnal, or auto (for the default behavior).

export MMCORE_PLUS_SIGNALS_BACKEND=psygnal
set MMCORE_PLUS_SIGNALS_BACKEND=psygnal
# before instantiating CMMCorePlus
import os
os.environ["MMCORE_PLUS_SIGNALS_BACKEND"] = "psygnal"
$env:MMCORE_PLUS_SIGNALS_BACKEND = "psygnal"

Connecting callbacks to events#

To connect a callback to an event, use the connect method of specific event emitter that you would like to listen to. (All event backends support the same connection/disconnection API.)

Example: Connecting callbacks

Given a CMMCorePlus object core:

from pymmcore_plus import CMMCorePlus

core = CMMCorePlus()

Register a callback to listen to property changes on the CMMCorePlus:

@core.events.propertyChanged.connect
def on_property_changed(dev: str, prop: str, value: str):
    print(f"Property {prop!r} on device {dev!r} changed to {value}")

Register a callback to process data during an acquisition sequence:

@core.mda.events.frameReady.connect
def on_image_captured(data: np.ndarray, event: useq.MDAEvent, metadata: dict):
    print(f"Event index {event.index} captured with shape {data.shape}")

The signature of the callback function should match the signature of the event emitter's signal. See API documentation for the specific event signatures.

You may disconnect a callback from an event by calling the disconnect method of the event emitter with the callback function as the argument.

Example: Disconnecting callbacks

core.events.propertyChanged.disconnect(on_property_changed)