protocols#
Protocol definitions for hardware instruments and data management.
This module defines the core interfaces that standardize behavior across the mesofield project, allowing for interoperability between different hardware instruments, data producers, and data consumers.
Protocol Implementation Notes#
When implementing these protocols, there are two approaches:
Direct inheritance (for regular classes without metaclass conflicts):
class MySensor(DataAcquisitionDevice): def __init__(self): self._init_logger() # Implement required methods and attributes
Duck typing (for classes with existing inheritance or metaclass conflicts, e.g.
QThread):class MyQThreadSensor(QThread): def __init__(self): super().__init__() self._init_logger() self.device_type = "sensor" self.device_id = "my_sensor"
The second approach is necessary for Qt classes (QObject, QThread,
QWidget) or any class that already uses a metaclass. Protocol checking
uses duck typing internally, so both approaches work with our system.
- class mesofield.protocols.Procedure[source]#
Bases:
ProtocolProtocol defining the standard interface for experiment procedures.
- class mesofield.protocols.HardwareDevice[source]#
Bases:
ProtocolProtocol defining the standard interface for all hardware devices.
Lifecycle:
initialize->arm->start->stop->shutdown. Every device exposesself.signals(amesofield.signals.DeviceSignals) carryingstarted,finished, anddataemitters.- arm(config)[source]#
Per-run preparation (writers, output paths, sequence build).
Called by
HardwareManager.arm_allimmediately beforestart_all. Devices without per-run prep may no-op.- Parameters:
config (ExperimentConfig)
- Return type:
None
- class mesofield.protocols.DataProducer[source]#
Bases:
HardwareDevice,ProtocolProtocol for hardware that produces data streamed to the DataQueue.
- class mesofield.protocols.FrameProcessor[source]#
Bases:
ProtocolProtocol for optional real-time per-frame consumers.
A FrameProcessor subscribes to a
DataProducercamera’ssignals.frame(carrying(img, idx, device_ts)) and emits a scalar result on its ownsignals.dataand on a Qt-compatiblevalueUpdated(time, value)signal. Seemesofield.processorsfor the threaded reference base class.- attach(camera)[source]#
Subscribe to
camera.signals.frameand start processing.- Parameters:
camera (DataProducer)
- Return type:
None
- class mesofield.protocols.StimulusDevice[source]#
Bases:
HardwareDevice,ProtocolProtocol for stimulus-presentation devices (e.g. PsychoPy).
Like
HardwareDevicebut explicitly not a data producer: consumers should not expectdatasignal emissions and should not callsave_data/get_data.
- class mesofield.protocols.DataConsumer[source]#
Bases:
ProtocolProtocol defining the interface for data-consuming components.
- class mesofield.protocols.ThreadedHardwareDevice[source]#
Bases:
objectMixin for implementing the HardwareDevice protocol with Python’s threading.
This mixin provides the basic structure for a hardware device that uses Python’s threading module. It handles the thread creation, starting, and stopping.
Example
class MySensor(ThreadedHardwareDevice): device_type = "sensor" device_id = "my_sensor" def __init__(self, config=None): super().__init__() self.config = config or {} def initialize(self): pass def _run(self): while not self._stop_event.is_set(): # Do work pass def get_status(self): return {"active": not self._stop_event.is_set()}
- class mesofield.protocols.AsyncioHardwareDevice[source]#
Bases:
objectMixin for implementing the HardwareDevice protocol with asyncio.
This mixin provides the basic structure for a hardware device that uses Python’s asyncio module. It handles the task creation, starting, and cancellation.
Example
class MySensor(AsyncioHardwareDevice): device_type = "sensor" device_id = "my_sensor" def __init__(self, loop=None, config=None): super().__init__(loop) self.config = config or {} def initialize(self): pass async def _run(self): while True: if self._should_stop(): break await asyncio.sleep(0.01) def get_status(self): return {"active": self._task is not None and not self._task.done()}