writer#
OME-TIFF + MP4 writers for MDASequences.
Two MDA output handlers, both plain classes exposing the sequenceStarted /
frameReady / sequenceFinished methods CMMCorePlus.run_mda connects by
name, and both emitting the <filename>_frame_metadata.json sidecar every
downstream mesofield parser (and the AcquisitionManifest metadata_path) reads:
OMEWriter– OME-TIFF, backed by the maintainedome-writerslibrary (incremental, flushed, no giant memmap pre-allocation). This replaced a memmap-based writer that accumulated ~9 GB of dirty pages in a 400 s dual-camera run and overflowed MMCore’s circular buffer.CV2Writer– MP4/AVI viacv2.VideoWriter.
Neither depends on pymmcore_plus.mda.handlers (deprecated upstream in favour
of ome-writers). NullWriter is a disk-free OMEWriter
subclass used only for benchmarking.
- class mesofield.data.writer.CustomJSONEncoder[source]#
Bases:
JSONEncoder- default(object)[source]#
Implement this method in a subclass such that it returns a serializable object for
o, or calls the base implementation (to raise aTypeError).For example, to support arbitrary iterators, you could implement default like this:
def default(self, o): try: iterable = iter(o) except TypeError: pass else: return list(iterable) # Let the base class default method raise the TypeError return super().default(o)
- class mesofield.data.writer.OMEWriter[source]#
Bases:
objectOME-TIFF writer backed by the maintained
ome-writerslibrary.Drop-in replacement for
CustomWriteras an MDA output handler (run_mda(output=...)): it exposes the three signal handlers the runner connects by name (sequenceStarted/frameReady/sequenceFinished) and drives anome_writers.OMEStream.Why this exists (measured, not assumed): the memmap-based
CustomWriterpre-allocates the full multi-GB OME-TIFF and writes into it vianumpy.memmapwith no flush, so dirty pages accumulate in RAM (≈9 GB in a 400 s dual-camera run) until flush stalls back up MMCore’s circular buffer and it overflows.ome-writerswrites incrementally with real flushing and no giant up-front allocation, and is the path pymmcore-plus is migrating to (pymmcore_plus.mda.handlersis deprecated).The mesofield contract is preserved: the
<filename>_frame_metadata.jsonsidecar every downstream parser (and the AcquisitionManifestmetadata_path) reads is still emitted fromfinalize_metadata(), built from the same per-frame pymmcore-plus metadata, accumulated here exactly as the deprecated_5DWriterBasedid.
- class mesofield.data.writer.NullWriter[source]#
Bases:
OMEWriterDisk-free
OMEWriterused only for benchmarking.Runs the identical MDA drain path (
frameReadyis still called per frame and metadata still accumulates) but never opens an ome-writers stream and never writes the sidecar, so no bytes hit disk and no dirty pages build up. Comparing a null-writer run against a real run isolates how much backlog/RAM the write path itself contributes.Enabled via
MESOFIELD_NULL_WRITER=1(seeBaseCamera._make_writer); never selected in normal operation.
- class mesofield.data.writer.CV2Writer[source]#
Bases:
objectWrite frames to an mp4/avi video using OpenCV.
Standalone MDA output handler – it exposes the three signal methods the runner connects by name (
sequenceStarted/frameReady/sequenceFinished, mirroringOMEWriter) and drivescv2.VideoWriterdirectly, so it no longer depends on the deprecatedpymmcore_plus.mda.handlers.OMETiffWriter.Two usage modes share the same codec/fourcc/metadata logic:
MDA-driven (
sequenceStarted/frameReady/sequenceFinished) when handed toCMMCorePlus.run_mdaas an output handler.Direct (
begin/add_frame/finish) for cameras that run their own capture loop (e.g.OpenCVCamera).
Both modes emit the same
<filename>_frame_metadata.jsonsidecar.- begin(width, height, is_color=True)[source]#
Open the underlying
cv2.VideoWriterfor a self-driven loop.