base#
Base procedure classes for implementing experimental workflows in Mesofield.
This module defines a generic Procedure orchestrator that contains
zero device-specific logic. Custom experiment subclasses live outside the
package (typically under experiments/<name>/procedure.py) and are
discovered via load_procedure_from_config(), which reads the optional
procedure_file and procedure_class fields from experiment.json.
Lifecycle (subclass hooks shown in bold):
initialize_hardware– bring devices upprerun– subclass hook (default: no-op)hardware.arm_all– per-run prep on every deviceconnect
hardware.primary.signals.finished->_cleanup_procedureon_started– subclass hook (default: no-op)hardware.start_allon_finished– subclass hook (default: no-op)save_data+ cleanup
- mesofield.base.processor(*, camera, plot=False, **plot_kwargs)[source]#
Mark a
Proceduremethod as a per-frame compute function.The decorated function is called as
func(self, img, idx, ts)and should return afloat | None. At procedure init the framework builds aFrameProcessorthat wraps it, attaches it to the hardware device whosedevice_idmatchescamera, registers it onDataManager, and (whenplot=True) tells the GUI to add aSerialWidget.plot_kwargsare forwarded straight to the widget — recognized keys:label,value_label,value_units,y_range,value_scale,max_points.Example:
class MyProcedure(Procedure): @processor(camera="meso", plot=True, label="Frame Mean") def frame_mean(self, img, idx, ts): return float(img.mean())
- class mesofield.base.ProcedureSignals[source]#
Bases:
QObjectAll procedure-level signals that a Qt GUI can connect to.
- class mesofield.base.Procedure[source]#
Bases:
objectGeneric orchestrator for a Mesofield experiment.
Subclass this in
experiments/<name>/procedure.pyand override the extension hooks (prerun(),on_started(),on_finished()) and/or the lifecycle methods (run(),save_data(),cleanup()) as needed. The base class never references a specific device type – multi-camera sync is driven by the YAMLprimary: trueflag andHardwareManager.start_all/stop_all.- load_config(hardware=None, experiment=None)[source]#
Hot-load a hardware YAML and/or experiment JSON into the live config.
The two inputs are independent: loading experiment params never touches hardware. Callers pass explicit paths (the GUI wizard resolves them from its pickers).
- define_config()[source]#
Subclass hook to declare experiment parameters in Python.
Override to return a
@dataclassinstance or a plain mapping; it is applied toconfigviaExperimentConfig.load_dict(), superseding anyexperiment.json. DefaultNone-> load JSON.- Return type:
- define_hardware()[source]#
Subclass hook to construct hardware devices in Python.
Override to return a list of pre-built device objects (imported and instantiated in the procedure file). They are handed to a fresh
HardwareManager, superseding anyhardware.yaml. DefaultNone-> load YAML. Device classes should be decorated with@DeviceRegistry.register(...)so the setup can later be exported to ahardware.yamlrig file viaHardwareManager.to_yaml.- Return type:
- on_finished()[source]#
Subclass hook called immediately after the primary device finishes.
- Return type:
None
- run()[source]#
Drive a standard experiment run.
Subclasses may override, but the default body is generic and handles any combination of devices declared in
hardware.yaml.- Return type:
None
- run_until_finished(timeout=None)[source]#
Run the procedure and block until cleanup completes.
Starts the procedure via
run(), then waits for theprocedure_finished(orprocedure_error) signal. HandlesKeyboardInterruptandtimeoutby invokingcleanup()automatically, so callers (e.g.__main__blocks in experiment scripts) do not need to wire up their own threading events.Parameters#
- timeout:
Optional hard ceiling in seconds. When
None(default), waits indefinitely for the primary device’sfinishedsignal. When provided, forces cleanup if the deadline passes.
Returns#
- bool
Trueif the procedure finished on its own,Falseif cleanup was forced by timeout or interrupt.
- mesofield.base.load_procedure_from_config(target)[source]#
Build the right
Procedurefor a launch target.targetmay be ahardware.yaml, anexperiment.json, a scriptedprocedure.py, an experiment directory, orNone. Discovery of the hardware/experiment pair is delegated to_resolve_target().When the experiment JSON declares
procedure_file+procedure_class, that subclass is imported and used; otherwise a baseProcedure.