Skip to content

preflight

tit.jobs.preflight

Refuse a job whose required inputs are not on disk, at submission instead of minutes later.

Background: an analyzer job in voxel space with a cortical DK40 target was accepted, queued, started, and only then died with FileNotFoundError: Atlas 'DK40' not found in .../fastsurfer/sub-101/mri, ... because that subject had no FastSurfer/recon-all volume parcellation. Nothing about that needed a running job to find out.

:func:preflight runs one small checker per job kind. Every check is a filesystem existence or name-correctness test built on :class:tit.paths.PathManager and the same resolution rules the runner uses (the analyzer's own :func:~tit.analyzer.field_selector.select_field_file and :attr:~tit.analyzer.analyzer.Analyzer._SURFACE_ATLAS_VOLUMES, tit.opt.flex.utils. eeg_net_csv_path, ...), so the check and the runner cannot disagree about where an input lives. No SimNIBS import, no mesh or volume is loaded; a config the checker cannot read (missing keys, wrong shapes) yields nothing here -- that is :mod:tit.jobs.config_check's job.

Each finding is a :class:MissingInput: what is missing, the named path it was expected at, and how to produce it ("run FastSurfer for sub-101", "run the L_Insula simulation first", "analyze in mesh space instead"). POST /api/jobs and POST /api/jobs/groups answer 422 with the list and create no job record.

MissingInput dataclass

MissingInput(what: str, expected_path: str | None, how_to_fix: str)

One input a job needs that is not on disk.

preflight

preflight(kind: str, config: dict[str, Any], project_dir: str) -> list[MissingInput]

Every input a kind job with config needs that is not on disk under project_dir.

An empty list means the sweep found nothing missing (not that the job will succeed). Unknown kinds and kinds with nothing to check return [].

Source code in tit/jobs/preflight.py
def preflight(
    kind: str, config: dict[str, Any], project_dir: str
) -> list[MissingInput]:
    """Every input a *kind* job with *config* needs that is not on disk under *project_dir*.

    An empty list means the sweep found nothing missing (not that the job will succeed).
    Unknown kinds and kinds with nothing to check return ``[]``.
    """
    checker = _CHECKERS.get(kind)
    if checker is None or not isinstance(config, dict):
        return []
    pm = get_path_manager(project_dir)
    return checker(pm, config)