signals#

Lightweight signaling hub used across mesofield.

Every HardwareDevice exposes a DeviceSignals instance on self.signals so the rest of the system (e.g. DataManager, Procedure) can connect uniformly without caring which backend the device uses.

Four signals form the standard contract:

started()

Emitted once the device is actively acquiring / running.

finished()

Emitted when the device has stopped on its own (e.g. an MDA sequence completed) or in response to stop(). The primary device’s finished is what triggers Procedure._cleanup_procedure().

data(payload, device_ts)

Emitted for every datum that should land on DataQueue. payload is the raw sample (frame index, encoder click count, NIDAQ count, …) and device_ts is the device-side timestamp (float seconds, optional).

frame(img, idx, device_ts)

Optional. Emitted by camera-like producers carrying the raw frame array in addition to the lightweight data emission. Subscribers use this for real-time processing (see mesofield.processors). Producers without per-sample raw payloads never emit on this signal.

The implementation wraps psygnal so emission is Qt-free, weakly referenced and thread-safe. GUI code that needs a Qt slot can use qt_bridge() to forward a psygnal.Signal into a pyqtSignal.

class mesofield.signals.DeviceSignals[source]#

Bases: object

Standard bundle of signals carried by every hardware device.

Defined as instance attributes (not class attributes) so each device owns its own emitters. psygnal.Signal instances are descriptors when declared on a class; we instantiate them directly here so they behave as plain emitters on the bundle.

__init__()[source]#
Return type:

None

mesofield.signals.qt_bridge(signal, qt_signal)[source]#

Forward emissions of a psygnal signal to a pyqtSignal.

Use from GUI code only. Both signals must accept the same argument arity. The connection is one-way: psygnal -> Qt.

Parameters:
  • signal (Any)

  • qt_signal (Any)

Return type:

None