Skip to content

app_defaults

tit.server.app_defaults

What the desktop run pages start with, where it differs from or adds to the config class's own defaults -- one table per job kind (ARCHITECTURE ยง6, "App defaults").

Three readers, one source:

  • dev/build_schema.py writes :data:APP_DEFAULTS into contracts/generated/config.schema.json as "x-app-defaults", which GET /api/schema serves; the Pre-processing, Simulator and Optimizer pages initialise their forms from it, over the schema's own default values (desktop/src/renderer/forms/appDefaults.tsx);
  • the server fills it into a config sent with created_by: "agent" (POST /api/validate, /api/plan, /api/jobs/preflight, /api/jobs, /api/jobs/groups) and into every proposal step (:mod:tit.server.proposals), so an agent sends only the fields it chose and still runs what the app would;
  • the agent plugin shows it in get_config_schema.

A kind with no entry (mex: the page starts at MExConfig's own defaults) takes the dataclass defaults only. Fields the agent sends always win; the merge is one level deep, so an electrode the agent sends replaces the table's whole electrode.

pre also takes what the Pre-processing page fills from the user's saved Settings (:mod:tit.surfer_settings, the page's toSubmitConfig): the FreeSurfer operations, and for a QSIPrep or QSIRecon step that settings dict -- processing preferences plus the per-process thread limit -- under the fields the agent sent in it. Charm options and the other resource limits are filled for every caller when the job is planned (resolve_job_threads).

with_app_defaults

with_app_defaults(kind: str, config: Any) -> Any

config over the table's entry for kind (a copy); anything but a dict is returned unchanged, for the caller's own validation to reject.

Source code in tit/server/app_defaults.py
def with_app_defaults(kind: str, config: Any) -> Any:
    """*config* over the table's entry for *kind* (a copy); anything but a dict is returned
    unchanged, for the caller's own validation to reject."""
    if not isinstance(config, dict):
        return config
    filled = {**copy.deepcopy(APP_DEFAULTS.get(kind, {})), **config}
    if kind == "sim" and config.get("carrier_only") and "output_fields" not in config:
        # The page's ticks include the envelope a carrier-only run lacks; leave the field to
        # SimulationConfig, whose default for that run is its carrier fields (as the page's is).
        del filled["output_fields"]
    return _with_saved_preferences(filled, config) if kind == "pre" else filled