spacr.qt.screens.batch¶
Batch Runner — the Tools module that spends the night for you.
The Plate Queue chains plates through one pipeline. This screen is the
other axis: arbitrary (module, settings) jobs in any order —
Mask → Measure → Classify (CV) → Classify (ML), then the same four again
with a different diameter, then a fifth plate’s Mask — built, validated, saved
to a file and run unattended.
The screen is deliberately thin. Everything it knows about a queue it learns
from spacr.batch, which is headless, torch-free and tested without Qt.
This file is only the part that has to be a GUI: pick a module and a settings
file, duplicate a job and edit it, reorder, validate, save/load, run, and watch
per-job status, progress and log.
Three decisions are visible to the user:
Jobs are validated when they are added, not when they run. A job whose settings file is missing, whose
srcis misspelled or whose module is GUI-only is refused at the Add button, with the reason inline. Finding that out at 3 a.m. from job 9 of 12 is what this whole module exists to prevent.No modal dialogs, ever. Every failure lands in the inline problems pane and in
BatchScreen.last_error. AQMessageBoxhangs a headless run (it did, inMakeMasksScreen), and this screen is exercised headlessly.The run happens off the GUI thread, and its completion handler comes back onto it.
PipelineWorker.finishedis emitted in the worker thread; every widget-mutating receiver therefore uses an explicit queued connection to a bound method of this GUI-thread widget.
Jobs run one at a time — they compete for one GPU — and each one is its own
spacr-run process, so a segfault in cellpose kills that job rather than
this window.
Classes¶
Build a queue of module+settings jobs, validate it, and run it overnight. |
Module Contents¶
- class spacr.qt.screens.batch.BatchScreen(parent=None, threaded: bool = True, runner: Callable[[Any, str, str], int] | None = None)[source]¶
Bases:
PySide6.QtWidgets.QWidgetBuild a queue of module+settings jobs, validate it, and run it overnight.
- Parameters:
parent – parent widget.
threaded – run the queue on a worker thread (the default). Tests pass
Falsefor deterministic, synchronous behaviour.runner –
(job, settings_path, log_path) -> exit_code, forwarded tospacr.batch.run_queue(). Defaults tospacr.batch.subprocess_runner()— one child process per job. Tests inject a fake so nothing real is ever segmented.
- Variables:
last_error – text of the most recent failure,
""when the last operation succeeded. Errors are only ever reported here and in the inline panes — never in a modal dialog.settled_thread – the thread the completion handler last ran on. Exists so a test can prove it was the GUI thread.
Build the screen, arm its drop zone and start the elapsed-time tick.
- Parameters:
parent – parent widget, or
None.threaded – run the queue on a worker thread. Set
Falsein tests sorunfinishes before it returns.runner – callable invoked per job as
(job, settings, log_path)returning an exit code;Noneuses the module’s own runner.
- add_job(module: str = '', settings: str = '', label: str = '', depends_on: Sequence[str] = (), overrides: Sequence[str] = ()) bool[source]¶
Add one job, validating it now. Problems land inline, never modally.
- Parameters:
module – module key; the combo’s current value when empty.
settings – settings file path; the settings box when empty.
label – display label; derived from the module and src when empty.
depends_on – ids of jobs that must succeed first.
overrides –
key=valuestrings, exactly like--set.
- Returns:
True when the job was added.
- duplicate_selected() bool[source]¶
Copy the selected job, never-run, and select the copy.
Building a night’s work means one job and eleven variations of it, so this is the button that actually gets used.
- load_queue_from(path: str) bool[source]¶
Replace the queue with the one in
path. Errors land inline.- Parameters:
path – queue JSON file read with
spacr.batch.load_queue(); on success it also becomes the file the run keeps up to date.
- move_selected(offset: int) bool[source]¶
Move the selected job
offsetplaces (negative is earlier).- Parameters:
offset – number of queue places to move the selected job; negative moves it earlier, and the new position is clamped to the queue.
- queue() spacr.batch.Queue[source]¶
The live
spacr.batch.Queuethis screen is editing.
- result() spacr.batch.QueueResult | None[source]¶
The
spacr.batch.QueueResultof the last run, or None.
- row_status(row: int) str[source]¶
Status text shown in
row(test/introspection helper).- Parameters:
row – zero-based table row; an empty string is returned when it has no Status cell.
- row_values(row: int) List[str][source]¶
Text of every cell in
row(test/introspection helper).- Parameters:
row – zero-based table row; a missing cell reads as an empty string.
- run() bool[source]¶
Validate, then run the queue off the GUI thread.
- Returns:
True when the run started (or, unthreaded, completed).
- save_queue_to(path: str) bool[source]¶
Write the queue to
pathatomically. Errors land inline.- Parameters:
path – destination queue JSON file, written by
spacr.batch.save_queue(); on success it also becomes the file the run keeps up to date.
- select_job(job_id: str) bool[source]¶
Select the row for
job_id.- Parameters:
job_id – identifier of the queued job; False is returned when no row shows it.
- selected_job() spacr.batch.Job | None[source]¶
The
spacr.batch.Jobfor the selected row, or None.By the job’s id, never by the row number: the table sorts, so the third row is not the third job once the user has clicked a header.
- set_runner(runner: Callable[[Any, str, str], int] | None) None[source]¶
Replace the per-job runner. None restores the subprocess default.
- Parameters:
runner – callable
runner(job, settings_path, log_path)returning the job’s exit code, passed tospacr.batch.run_queue()for every job; None letsrun_queue()use its subprocess default.
- stop() bool[source]¶
Ask the queue to stop after the job that is currently running.
Killing a job mid-write would leave exactly the half-written artifact the skip rules exist to avoid, so the running job is always allowed to finish.
- validate_now(quiet: bool = False) List[spacr.batch.Problem][source]¶
Validate the whole queue and show every problem inline at once.
- Parameters:
quiet – do not overwrite the status line when the queue is clean.
- Returns:
the problems, errors and warnings mixed.