devices#
- class mesofield.devices.BaseDevice[source]#
Bases:
objectDefault lifecycle skeleton for non-Qt hardware devices.
Constructor accepts an optional
cfgmapping (the YAML stanza for this device). Common keys are auto-extracted:id/device_id->self.device_idprimary: true->self.is_primary
A logger is created automatically as
f"{module}.{class}[{device_id}]".- arm(config)[source]#
Per-run preparation. No-op by default.
- Parameters:
config (ExperimentConfig)
- Return type:
None
- property calibration: Dict[str, Any]#
Device-specific constants worth recording with the data.
Default: everything in cfg that isn’t an orchestration key. Override on a subclass to curate the list explicitly.
- sidecars()[source]#
Auxiliary files this device writes alongside its primary output.
Default: none. Override to declare extra sidecars (masks, regions, derived parameter files) so they ride in the manifest with a role and schema_version instead of being discovered by glob.
The camera classes’ per-frame metadata JSON is the primary sidecar and lives on self.metadata_path – not here. Use this method for the extra files only.
Returns a list of mesokit_schema.SidecarEntry-shaped mappings or instances. The Procedure relativises any absolute paths.
- Return type:
- class mesofield.devices.BaseDataProducer[source]#
Bases:
BaseDeviceBase class for devices that stream samples to the DataQueue.
Subclasses produce data by calling
record(), which timestamps, appends to an in-memory buffer, and emitssignals.data(payload, ts)in one step.The default
save_data()writes the buffer as a two-column CSV (timestamp,payload). Override for binary or domain-specific formats.- arm(config)[source]#
Default
arm: clear buffer and resolveoutput_path.configis expected to exposemake_path(name, ext, bids)(seemesofield.config.ExperimentConfig).- Parameters:
config (ExperimentConfig)
- Return type:
None
- class mesofield.devices.BaseSerialDevice[source]#
Bases:
BaseDataProducerPolling device for line-based serial protocols (Arduino/Teensy/etc.).
Subclasses override
parse_line(). Optionally overridesetup_serial()for post-open initialisation (handshakes, buffer drain, configuring device-side parameters).Configuration keys read from
cfg:port(str, required whendevelopment_mode=False)baudrate(int, default 115200)timeout(float, default 0.1) — pyserial readline timeout.dtr(bool | None, default None) — set toFalseto suppress Arduino auto-reset on connect.Nonekeeps the OS default.connect_delay(float, default 0.0) — seconds to wait after opening the port before reads begin; common Arduinos need ~2.0. The input buffer is flushed after the delay.development_mode(bool, default False) — skip opening the port so the GUI / Procedure can launch without hardware.send_linebecomes a no-op; the polling thread idles.
- setup_serial()[source]#
Hook called once after the port is opened. Default no-op.
Override to send a handshake, query firmware version, configure device-side parameters, etc.
- Return type:
None
- send_line(payload, *, newline=b'\n')[source]#
Write a command to the device. Thread-safe with the reader.
Accepts
str(UTF-8 encoded) orbytes.newlineis appended unlesspayloadalready ends with it. Indevelopment_modethe bytes are logged and discarded. Returns the bytes that were written (or would have been).
- class mesofield.devices.Nidaq[source]#
Bases:
objectNIDAQ hardware control device.
This class implements the ControlDevice protocol via duck typing, providing all the necessary methods and attributes without inheritance.
- test_connection()[source]#
Pulse the configured DO line high for ~3 s as a connectivity test.
Logs the outcome; does not raise on failure (errors are surfaced via the logger).
- start()[source]#
Begin counting edges on
ctrand pulsinglinesfrom a thread.Configures both a counter-input task (rising-edge counts) and a digital-output task (camera trigger), then launches a worker thread that drives them on the configured
poll_interval.
- class mesofield.devices.MMCamera[source]#
Bases:
BaseCamera,DataProducer,HardwareDeviceMicro-Manager-backed camera.
Inherits the common camera surface (identity, output paths, manifest metadata,
arm/set_sequencedefaults,status,calibration) fromBaseCamera, and duck-types theDataProducer/HardwareDeviceProtocols so existing isinstance() checks keep working. The actual frame flow is driven by pymmcore-plus’s MDA event system; this class wires those events into the standardDeviceSignalsbundle and constructs aCustomWriter(OME-TIFF) orCV2Writer(MP4) for the output.- set_sequence(build_mda)[source]#
Build the MDA sequence (Micro-Manager backend only).
- Parameters:
build_mda (Callable[[DataProducer], Any])
- initialize()[source]#
Apply the YAML
propertiesblock to the underlying camera.Each
{device_id: {property: value}}pair is forwarded to the backend (core.setROIfor ROIs,core.setPropertyotherwise) with special handling for the syntheticfps,viewer_type, andauto_contrastkeys.
- start_led_sequence(pattern)[source]#
Start the LED pattern.
If
led_serialis configured on this camera, sends the configured raw byte sequences via MM’s SerialManager. Otherwise falls back to the originalArduino-Switch.State.loadSequence/startSequencepath.- Return type:
None
- stop_led_sequence()[source]#
Stop the LED pattern (mirror of
start_led_sequence()).- Return type:
None
- start()[source]#
Launch the MDA sequence non-blocking.
- Returns:
Always
True. The sequence runs asynchronously on the camera backend; lifecycle is reported viaself.signals.- Return type:
- stop()[source]#
Stop acquisition.
Non-primary Micro-Manager cameras must be told explicitly to halt their sequence acquisition — the primary camera’s MDA driver does not stop them.
- Return type:
- start_live()[source]#
Begin continuous (untimed) sequence acquisition for preview.
- Return type:
None
- class mesofield.devices.OpenCVCamera[source]#
Bases:
BaseCamera,QThreadBackground-thread OpenCV camera capturing to MP4.
- Emits via
self.signals(amesofield.signals.DeviceSignals): signals.started/signals.finishedfor lifecycle.signals.data(idx, device_ts)per frame, consumed byDataManager.register_hardware_device().
- Plus Qt live-preview signals (GUI-only, decoupled from DataQueue):
frame_ready(np.ndarray)/image_ready(np.ndarray).
Inherits the common camera surface (identity, output paths, manifest metadata,
arm/set_sequencedefaults) fromBaseCamera, and runs its own capture loop on top ofQThread.- set_writer(make_path)[source]#
Resolve the output path and build the
CV2Writer.BaseCamera.set_writerresolvesoutput_path, constructs theCV2Writer(the project’s shared MP4 writer), and copies its sidecar path ontometadata_path. The capture loop drives the writer directly viabegin/add_frame/finish.
- start()[source]#
Spawn the capture thread and begin writing frames to MP4.
- Returns:
Trueif the thread started,Falseif it was already running.- Return type:
- shutdown()[source]#
Tear down the capture thread.
stop()joins the capture thread; itsrun()finally-block releases theCV2Writerand writes the sidecar JSON.- Return type:
None
- Emits via
- class mesofield.devices.EncoderSerialInterface[source]#
Bases:
BaseSerialDeviceTeensy encoder/treadmill device.
Constructor accepts either a cfg dict (
BaseSerialDevice-style) or legacy positional/keyword args(port, baudrate)for backward compatibility withmesofield.hardware.- Parser#
alias of
TreadmillSource
- class mesofield.devices.MockEncoderDevice[source]#
Bases:
BaseDataProducerSynthetic encoder that records random click counts.
- class mesofield.devices.MockFrameProducer[source]#
Bases:
BaseCamera,BaseDataProducerSynthetic camera producing real OME-TIFF + frame metadata JSON.
- arm(config)[source]#
Per-run prep: set up the writer + (optionally) an MDA sequence.
The default body fits both MMCamera (which needs a sequence) and OpenCV/Mock (where
set_sequenceis a no-op). Subclasses override only when they need additional prep.- Parameters:
config (ExperimentConfig)
- Return type:
None
- snap()[source]#
Capture a single frame outside any recording, return it as an ndarray.
Used by the GUI’s snap button. Implementations should NOT alter recording state – snap is preview-only – but they SHOULD call
_save_snap_png()so each snap also lands a*_snap.png.- Return type:
- start_live()[source]#
Begin continuous live preview WITHOUT writing to disk.
Subscribers receive frames via
image_ready(Qt) /signals.data(psygnal). No recording side-effects; pair withstop_live().- Return type:
None
- stop_live()[source]#
End the continuous live preview started by
start_live().- Return type:
None