magscope.scope#
Core orchestration for the MagScope application.
MagScope is the parent process that builds every other manager process,
connects them with shared resources, and relays inter-process messages until
shutdown. Its responsibilities span the full application lifetime:
Loading persisted settings from
QSettings, with optional YAML import/export available through the user interface.Constructing manager processes (camera, bead lock, GUI, scripting, video processing, and optional hardware integrations) and wiring them to shared locks, buffers, and IPC pipes.
Running the main IPC loop that forwards typed IPC commands between processes and supervises orderly shutdown.
MagScope.start prepares the shared resources, registers scriptable hooks,
starts each process, and then loops until a quit command is received.
Example
Run the simulated scope with its default managers:
>>> from magscope.scope import MagScope
>>> scope = MagScope()
>>> scope.start()
For headless automation you can add hardware adapters and GUI panels before
invoking MagScope.start():
>>> scope.add_hardware(custom_hardware_manager)
>>> scope.add_control(CustomPanel, column=0)
>>> scope.start()
MagScope constructs the following high-level pipeline:
CameraManager → VideoBuffer → VideoProcessorManager → UIManager
and
BeadLockManager → MatrixBuffer → UIManager
Every manager receives shared locks, pipes, and configuration from the main process so that real-time video frames, bead tracking data, and scripted events remain synchronized.
Attributes#
Classes#
Coordinate MagScope managers, shared resources, and IPC. |
Module Contents#
- class magscope.scope.MagScope(*, verbose: bool = False, print_ipc_commands: bool = False, print_script_commands: bool = False)[source]#
Coordinate MagScope managers, shared resources, and IPC.
MagScopeowns references to every manager process, shared buffer, and IPC primitive used by the application. Instances can be customized by adding hardware managers, GUI controls, or time-series plots before callingstart(). Once started, the instance supervises manager lifetimes, relays messages, and coordinates shutdown when a quit signal is broadcast over the IPC bus. The orchestrator is a singleton: attempts to construct a second instance raiseTypeError. Each instance is single-use: callingstart()while an instance is already running logs a warning, and invokingstart()after the instance has quit raises an error. Usestop()to request a graceful shutdown; it blocks until all managers acknowledge the quit sequence and exit.- _hardware: dict[str, magscope.hardware.HardwareManagerBase][source]#
- _hardware_buffers: dict[str, magscope.datatypes.MatrixBuffer][source]#
- processes: dict[str, magscope.processes.ManagerProcessBase][source]#
- command_registry: magscope.ipc.CommandRegistry[source]#
- lock_names: list[str] = ['BeadRoiBuffer', 'LiveProfileBuffer', 'TracksBuffer', 'VideoBuffer',...[source]#
- live_profile_buffer: magscope.datatypes.LiveProfileBuffer | None = None[source]#
- bead_roi_buffer: magscope.datatypes.BeadRoiBuffer | None = None[source]#
- tracks_buffer: magscope.datatypes.MatrixBuffer | None = None[source]#
- video_buffer: magscope.datatypes.VideoBuffer | None = None[source]#
- start()[source]#
Launch all managers and enter the main IPC loop.
The startup sequence performs the following steps:
Collect every manager (built-in and user-supplied hardware) and assign them a shared
processesmapping for bookkeeping.Load configuration values, prepare shared memory buffers, locks, pipes, and register scriptable methods.
Spawn each manager process and then forward IPC messages until a quit signal is observed.
When a quit message is received the method joins every process before returning control to the caller.
- stop() None[source]#
Request a graceful shutdown and wait for every manager to exit.
stopmirrors a quit request sent from any manager process: it broadcasts a quit message, drains outstanding IPC, and blocks until all managers have joined. Afterstopcompletes the instance is permanently terminated and cannot be restarted.
- add_hardware(hardware: magscope.hardware.HardwareManagerBase)[source]#
Register a hardware manager so its process launches with MagScope.
- add_control(control_type: type[magscope.ui.controls.ControlPanelBase], column: int)[source]#
Schedule a GUI control panel to be added when the UI manager starts.
- add_timeplot(plot: magscope.ui.plots.TimeSeriesPlotBase)[source]#
Schedule a time-series plot for inclusion in the GUI at startup.
- property print_ipc_commands: bool[source]#
Return whether
start()should print IPC commands and exit early.
- property print_script_commands: bool[source]#
Return whether
start()should print script commands and exit early.
- _coerce_settings(value: magscope.settings.MagScopeSettings | dict) magscope.settings.MagScopeSettings[source]#
- classmethod _reset_singleton_for_testing() None[source]#
Clear the singleton registry so tests can create fresh instances.
- set_verbose_logging(enabled: bool = True) None[source]#
Toggle informational console output for MagScope internals.
- _ensure_not_terminated() None[source]#
Prevent reusing a MagScope instance after it has been stopped.
- _apply_logging_preferences() None[source]#
Apply the current verbosity preference to the logging system.
- _dismiss_startup_splash_if_pending() None[source]#
Dismiss the splash while startup is still waiting on the UI.
- _check_startup_splash_timeout() None[source]#
Dismiss the splash if UI startup has been pending too long.
- _collect_processes() None[source]#
Assemble the ordered list of manager processes to supervise.
ScriptManager must remain first so that the
@register_script_commanddecorator binds correctly before other managers start.
- print_registered_commands() None[source]#
Print the registered IPC commands without launching managers.
- print_registered_script_commands() None[source]#
Print the registered script commands without launching managers.
Load configuration and prepare shared resources for all managers.
- _read_command(pipe: multiprocessing.connection.Connection) magscope.ipc_commands.Command | object | None[source]#
Retrieve a command from
pipeif one is waiting.
- _process_command(command: magscope.ipc_commands.Command) bool[source]#
Route a valid command and indicate whether the IPC loop should break.
- _route_command(command: magscope.ipc_commands.Command) bool[source]#
Dispatch a command based on its destination.
Returns
Truewhen the IPC loop should stop iterating over the current set of pipes (for example, immediately after handling a quit broadcast). This mirrors the previous behavior of breaking out of thereceive_ipcloop once a quit command has been processed.
- _dispatch_mag_scope_command(command: magscope.ipc_commands.Command, spec) None[source]#
Handle commands destined for the MagScope orchestrator.
- _handle_broadcast_command(command: magscope.ipc_commands.Command, spec=None) bool[source]#
Broadcast a command to all processes and handle quit semantics.
Returns
Truewhen the caller should stop processing the current IPC loop (e.g., after handling a quit command).
- log_exception(process_name: str, details: str) None[source]#
Surface an exception raised in a managed process.
- startup_ready(process_name: str = 'UIManager') None[source]#
Dismiss the startup splash once the UI process is ready.
- _reset_camera_health_logging_state() None[source]#
Start a fresh sampling window for periodic camera health logging.
- _log_camera_health_if_due() None[source]#
Emit a 1-minute camera health summary while verbose logging is enabled.
- _drain_child_pipes_after_quit() None[source]#
Drain child pipes until they acknowledge the quit event.
Create and distribute shared locks, pipes, buffers, and metadata.
Share locks, pipes, and configuration with each process.
This step must occur before any manager processes are started so they can inherit references to shared multiprocessing primitives.
Instantiate shared memory buffers used throughout the application.
- _setup_pipes() dict[str, multiprocessing.connection.Connection][source]#
Create duplex pipes that allow processes to exchange messages.
- update_settings(settings: magscope.settings.MagScopeSettings | dict) None[source]#
Replace the active settings and broadcast them to all managers.