base_camera#
Shared surface for camera-shaped devices.
Three concrete cameras converge on this base:
mesofield.devices.cameras.MMCamera(Micro-Manager backend)
mesofield.devices.cameras.OpenCVCamera(OpenCV/UVC)
mesofield.devices.mocks.MockFrameProducer(synthetic)
They have wildly different acquisition loops (mmcore-driven MDA vs Qt thread vs synthetic frame generator) so we don’t try to unify the run-loop here. What we DO unify is the surface every camera must expose:
Identity & cosmetic attrs the MDA GUI reads (
name,viewer,auto_contrast,core,backend).Output paths and metadata sidecar plumbing.
The standard lifecycle hooks (
arm,set_writer,set_sequence,shutdown,status,calibration).The
DeviceSignalsbundle thatDataManagersubscribes to (signals.started,signals.finished,signals.data).
Subclasses keep their backend-specific initialize, start, stop,
save_data, and writer setup.
Design notes:
BaseCamerais a regular class – not a Protocol – so subclasses can multiply-inherit alongside Qt’sQThread(OpenCVCamera), pymmcore-plus’sDataProducer/HardwareDeviceProtocols (MMCamera), and our pure-PythonBaseDataProducer(MockFrameProducer).We avoid
BaseCamera.__init__to dodge multiple-inheritancesuper()chains with QThread. Subclasses call_init_camera_surface()after whatever parent__init__they need.
- class mesofield.devices.base_camera.BaseCamera[source]#
Bases:
objectCommon camera surface (no Qt, no acquisition loop).
Subclasses call
_init_camera_surface()from their__init__after any superclasssuper().__init__()calls. Overrideset_writer(),set_sequence(),start(),stop(),save_data(), andget_data()as needed.- 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
- set_writer(make_path)[source]#
Generate the camera’s output path and construct the writer.
Resolves
self.output_pathviamake_path, then instantiates the writer that_make_writer()picks forself.file_typeand copies the writer’s sidecar filename ontoself.metadata_pathfor the AcquisitionManifest. Subclasses override only when they need additional plumbing on top (e.g. OpenCVCamera resetting its capture-loop timing).
- 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.
- 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
- property calibration: Dict[str, Any]#
Camera-specific constants worth recording in the AcquisitionManifest.