tvbo run

Execute a SimulationStudy or SimulationExperiment against a chosen backend, with optional sharding, container isolation, and HPC dispatch.

Synopsis

tvbo run SPEC
    [--backend, -b BACKEND]
    [--out-dir, -o DIR]
    [--experiment NAME]
    [--duration MS]
    [--set PATH=VALUE ...]
    [--limit N]
    [--engine, -e {local|slurm|snakemake|nextflow}]
    [--container IMAGE]
    [--shard i/N]

Flags

Flag Default Purpose
--backend, -b tvboptim Execution backend. See tvbo workflow backends for the full list.
--out-dir, -o (none) Directory to write results into. When omitted, no files are written.
--experiment (all) If SPEC is a Study, run only this experiment (by key/name/label/numeric id). A comma-list (2,3,20,30) runs several.
--duration (spec) Override integration.duration in milliseconds (shorthand for --set integration.duration=…).
--set (none, repeatable) Override any experiment metadata field for this run only — the recipe file is not touched. Dotted PATH traverses attributes and keyed collections; VALUE is coerced (bool/int/float/JSON). See Overriding metadata.
--limit (none) Run at most N cells of the sweep (a spread sample) without needing to know the grid size. Ignored when --shard is given.
--engine, -e local local runs in-process; the others re-emit via tvbo workflow ENGINE and submit.
--container (none) OCI image to re-exec inside (Singularity preferred, then Docker).
--shard (none) i/N — shard the sweep grid: cell j runs iff j % N == i. (--slurm-chunk is a deprecated alias.)

Behaviour by kind

tvbo run dispatches on the resolved SPEC kind:

Kind Behaviour
experiment Calls experiment.run(format=BACKEND, **overrides).
study Iterates over study.experiments; if --experiment NAME is given, only that one runs.
anything else Errors with tvbo run does not yet support kind=<kind>.

Custom code in a recipe (code/)

A recipe can reference custom Python by bare module name — a network builder (builder: {module: my_networks}) or an analysis callable (callable: {module: my_analysis}). tvbo resolves these by making the recipe’s code/ subdir importable when the recipe loads, so the modules resolve with no PYTHONPATH prefix:

study/
  recipe.yaml            # references module: my_analysis
  code/my_analysis.py    # found automatically on load
tvbo run recipe.yaml --experiment 3      # not: PYTHONPATH=code tvbo run …

The paths go to the front of sys.path on load and stay there (callables resolve lazily during the run, not only at load). The convention carries to the cluster: tvbo workflow bundles the referenced local modules into the kit’s code/ and the emitted job puts it on PYTHONPATH. Modules installed as packages are used as-is; only local .py files travel with the kit.

Overriding metadata for a run (--set)

Keep one recipe as the ground truth and let the CLI run it with different settings — no divergent copy to drift out of sync. Each --set PATH=VALUE mutates the loaded experiment before code generation; the file on disk is never modified.

# Smoke-test a long study cheaply, straight from the real recipe:
tvbo run study.yaml --experiment 3 \
    --set integration.duration=1.0 \
    --set integration.transient_time=0.5 \
    --set observations.lyapunov.analysis.parameters.n_steps.value=4 \
    -o ./smoke

PATH is a dotted walk through attributes and keyed collections (LinkML keyed dicts such as observations, parameters): integration.step_size, observations.<name>.analysis.parameters.<name>.value, and so on. VALUE is coerced to bool/int/float, or parsed as JSON when it starts with [/{ (e.g. --set …=[0,2]), else kept as a string. Repeat --set for several overrides; the run logs each one it applies.

--duration is the shorthand for --set integration.duration=…. A collection key that itself contains a dot (e.g. an exploration space keyed by KuramotoInertia.K) can’t be addressed this way — reduce sweep size with --limit or --shard instead.

Sharding (--shard i/N)

When the experiment carries one or more Explorations, --slurm-chunk lets a single Slurm array task run a deterministic subset of cells:

# Array task 3 out of 16 — runs cells where j % 16 == 3
tvbo run experiment:Sweep --backend jax --slurm-chunk 3/16 -o ./out

Internally, the planner enumerates the cartesian product of all exploration axes and skips cells whose index mod N is not equal to i. Each cell is written to <out_dir>/cell_<j:06d>/. This is what the workflow templates emit by default for Slurm.

Container re-exec (--container IMAGE)

tvbo run experiment:JR_MEG --backend jax \
    --container ghcr.io/the-virtual-brain/tvbo:0.7.0 -o ./out

If singularity is on PATH (or SINGULARITY_BIND is set), the command re-execs as:

singularity exec --bind $PWD:$PWD <image> tvbo <original argv>

Otherwise it falls back to Docker:

docker run --rm -e TVBO_IN_CONTAINER=1 -v $PWD:$PWD -w $PWD <image> tvbo <original argv>

The TVBO_IN_CONTAINER=1 environment variable is set in the inner invocation to prevent recursive re-exec.

Engine dispatch (--engine)

Non-local engines re-emit the run as a workflow kit and submit it:

tvbo run experiment:JR_MEG --engine slurm --backend jax -o ./run-001

is equivalent to:

tvbo workflow slurm experiment:JR_MEG --backend jax -o ./run-001/run.sbatch
sbatch ./run-001/run.sbatch

For snakemake and nextflow, only the artefact is written — no automatic launcher is invoked. See HPC patterns for the full lifecycle.

Examples

# Local run on the default backend, no output saved
tvbo run experiment:JR_MEG_FrequencyGradient_Optimization

# Local run with JAX, write results
tvbo run experiment:JR_MEG -b jax -o ./out

# Override the integration window
tvbo run experiment:JR_MEG -b jax --duration 30000 -o ./out

# Pick one experiment from a multi-experiment study
tvbo run study:Schirner2023 --experiment JR_MEG -b jax -o ./out

# Submit via Slurm in one command
tvbo run experiment:JR_MEG --engine slurm -b jax -o ./run-001

# Container-isolated run
tvbo run experiment:JR_MEG -b jax --container ghcr.io/the-virtual-brain/tvbo:0.7.0

See also