Source code for solprop.driver.scan

# SPDX-FileCopyrightText: 2026 John C. Travers and contributors
#
# SPDX-License-Identifier: GPL-3.0-or-later

"""Describe indexed parameter scans and dispatch independent simulations."""

from collections.abc import Callable, Sequence
from pathlib import Path
from typing import Literal

from solprop.driver._scan_model import Scan, ScanPoint
from solprop.driver._scan_run import execute_scan
from solprop.driver.executors import Executor
from solprop.driver.simulation import Simulation
from solprop.log import ProgressChoice, ScanReporter, StopFlag
from solprop.output.schema import RecipeRecord
from solprop.processing.scans import Reduction, ScanOutput

__all__ = ["Scan", "ScanPoint", "run_scan"]


[docs] def run_scan( # noqa: PLR0913 - the public scan controls scan: Scan, build: Callable[[ScanPoint], Simulation], *, output: Path | str, executor: Executor | None = None, reductions: Sequence[Reduction] = (), fields: Literal["none", "planes", "all"] = "none", field_planes: Sequence[int] = (), stats: Literal["all", "none"] | Sequence[str] = "all", retry_failed: bool = False, stale_age: float = 600.0, progress: ProgressChoice | ScanReporter = "auto", stop: StopFlag | None = None, recipe: RecipeRecord | None = None, ) -> ScanOutput: """Run selected points and return a reader for their collected file. Parameters ---------- scan : Scan Complete scan or selection of global indices. build : callable Build a Simulation from a ScanPoint. Noise the builder leaves unseeded is drawn from ``point.seed``, or, on a scan without seeds, from one derived from the scan's name and the point's global index; noise it seeds itself must use ``point.seed``. Pool builders must be pickleable module-level callables. Cache a base simulation lazily inside this callable for one translation per worker. output : pathlib.Path or str Collected HDF5 path. Matching completed points are skipped on rerun. executor : Executor or None, optional Execution policy. None uses the CLI policy, or Local outside the CLI. reductions : sequence of Reduction, optional Worker-side calculations with declared shape, dtype, units and provenance. fields : {'none', 'planes', 'all'}, optional Retain no fields, selected planes, or every saved plane. field_planes : sequence of int, optional Saved-plane indices for ``fields='planes'``; negative indices are allowed. stats : {'all', 'none'} or sequence of str, optional Retained statistics; all includes periodic rows. None is discouraged: statistics are the diagnostics needed to assess a scan. retry_failed : bool, optional Retry previously failed points; false leaves them recorded as failures. stale_age : float, optional Positive lease age in seconds before abandoned running points are recovered. progress : {'auto', 'bar', 'log', 'none'} or solprop.log.ScanReporter, optional One outer progress display; individual runs never draw their own bars. A :class:`~solprop.log.ScanReporter` replaces the display and is told when the scan and each point start and finish; a :class:`~solprop.log.WatchingScanReporter` also receives each point's run on ``Local`` and ``Pool`` (SEP 41, S4). stop : object or None, optional The scan's stop flag: any object with an ``is_set()`` method, such as a :class:`threading.Event` (SEP 41, S17). Once it is set no further point is dispatched; ``Local`` and ``Pool`` stop the points in flight within one step, a ``Pool`` through a message on each busy worker's pipe; ``Batch`` stops between groups. A stopped point is not committed, so a rerun computes it again, and the scan returns normally, its file holding the points finished before the stop; it logs at ``INFO`` that it stopped, and a scan reporter is told ``"stopped"`` for each stopped point. ``Queue`` and ``Slurm`` refuse it. recipe : solprop.output.schema.RecipeRecord or None, optional The recipe the scan was built from, which the scan file records once, so that it reopens with its setup (SEP 41, S2); :meth:`solprop.recipe.core.Recipe.scan` passes it among its keywords. ``None`` records none. Returns ------- solprop.processing.scans.ScanOutput Reader with global indices, masked incomplete points and exact statistics. Raises ------ DriverError If controls are invalid, the executor cannot run the builder, or `stop` is given to a ``Queue`` or ``Slurm`` executor. OutputError If the file belongs to a different scan or stored configuration. """ return execute_scan( scan, build, output=output, executor=executor, reductions=reductions, fields=fields, field_planes=field_planes, stats=stats, retry_failed=retry_failed, stale_age=stale_age, progress=progress, stop=stop, recipe=recipe, )