playback#
Replay a saved mesofield session as if it were a live acquisition.
A playback run instantiates PlaybackCamera and PlaybackEncoder
devices that read recorded OME-TIFF frames and encoder CSVs off disk and re-emit
them through the standard DeviceSignals bundle. The
DataManager registers them like any other
producer, so the in-memory DataQueue, every
subscribed processor and the GUI viewer see the data move through the same
pipeline they would during a live capture.
Public surface used by mesofield playback <experiment_dir>:
discover_playback_context()– locatemanifest.json, build aPlaybackProcedurewith one playback device per producer.launch_playback_app()– run that procedure inside the standardMainWindow.
Playback is read-only: devices do not allocate writers, and the procedure
skips the dataqueue logger, the per-device save_data step, and the
manifest.json re-write so the original session folder is left untouched.
- class mesofield.playback.PlaybackClock[source]#
Bases:
objectWall-clock anchor shared by every playback device in a session.
t0_originalis the earliest device timestamp across all producers in the manifest;t0_wallis captured atarm()time. Each replay thread sleeps untilt0_wall + (original_ts - t0_original) / speed, which keeps the two cameras and the encoder in their original relative order.
- class mesofield.playback.PlaybackCamera[source]#
Bases:
BaseCamera,BaseDataProducerReplays an OME-TIFF + sidecar JSON pair through the standard camera surface.
- 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]#
No-op: playback never allocates a writer.
- Parameters:
make_path (Any)
- 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:
ndarray | None
- 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
- class mesofield.playback.PlaybackEncoder[source]#
Bases:
BaseDataProducerReplays a saved encoder/treadmill CSV through
signals.data.- 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.playback.PlaybackContext[source]#
Bases:
objectBundle returned by
discover_playback_context().
- class mesofield.playback.PlaybackSession[source]#
Bases:
objectOne
(subject, session)directory discovered on disk.Holds just enough metadata for the ConfigController dropdowns to present a choice: the parsed subject/session ids, the absolute session directory, the path to its manifest, and the task/protocol read from the manifest’s session block (used as display hints and to seed
ExperimentConfig).
- mesofield.playback.discover_playback_context(experiment_dir, *, speed=1.0, loop=False)[source]#
Build a
PlaybackContextfrom a recorded session directory.- Parameters:
- Return type:
- mesofield.playback.discover_playback_sessions(experiment_dir)[source]#
Enumerate every
data/sub-*/ses-*/manifest.jsonunder experiment_dir.Falls back to scanning experiment_dir itself when it points directly at a session directory. Sessions are returned sorted by (subject, session) so the dropdowns have a predictable order.
- Parameters:
experiment_dir (Path)
- Return type:
- class mesofield.playback.PlaybackBrowser[source]#
Bases:
objectDrives
ConfigControllerfor playback.Two responsibilities:
Re-seed
ExperimentConfig.subjectsfrom the set of recorded sessions on disk so the subject dropdown lists what is actually playable, and register the per-subject session ids asregister_choiceson thesessionkey so it renders as a dropdown.When the user picks a different subject or session, tear down the current playback procedure and swap a freshly-built one into
MainWindow, re-using the existing widget-rebuild path (_build_acquisition_ui+_on_config_applied).
Implementation note: the actual swap is deferred via
QTimer.singleShotbecause the change callback fires inside a QComboBox signal handler – rebuilding the parent ConfigController during that callback would delete the QObject that emitted the signal.
- mesofield.playback.launch_playback_app(context, *, browser_sessions=None)[source]#
Open the standard mesofield GUI against a
PlaybackContext.When
browser_sessionsis supplied, aPlaybackBrowseris wired into the MainWindow’s ConfigController so the subject/session dropdowns swap playback targets on change.- Parameters:
context (PlaybackContext)
browser_sessions (List[PlaybackSession] | None)
- Return type: