Local Executor#
The local backend is the default. It runs simulations directly on the
current machine, either in a single process or across a local process pool.
This is the right choice for notebooks, workstation batch runs, and anything
that fits on one machine.
Configuration#
execution:
backend: local
n_workers: 4 # omit or set to 1 for single-process
Or override at the CLI without touching config.yaml:
stilt run ./project --backend local --n-workers 4
n_workers: 1 runs all simulations inline in the calling process (no
subprocess pool). n_workers > 1 spawns a joblib-backed process pool.
The CLI always blocks until all local workers finish.
Python and notebook usage#
Build a model in memory and call run():
import stilt
model = stilt.Model(
project="./case",
receptors=[
stilt.PointReceptor(
time="2023-01-01 12:00:00",
longitude=-111.85,
latitude=40.77,
altitude=5.0,
)
],
config=stilt.ModelConfig(
mets={
"hrrr": stilt.MetConfig(
directory="/data/hrrr",
file_format="%Y%m%d_%H",
file_tres="1h",
)
}
),
)
model.run()
model.run() is equivalent to stilt run from the CLI — it registers
pending simulations and dispatches them through the configured backend.
Querying outputs#
model.simulations is a lazy collection backed by the output index. Use
it to inspect or filter completed work without re-running:
ids = model.simulations.ids()
incomplete = model.simulations.incomplete()
For cross-simulation access, use the model-level collections:
trajectory_paths = model.trajectories.paths()
footprints = model.footprints["default"].load()
Register first, execute later#
For more control, split registration from execution:
sim_ids = model.register_pending(scene_id="tower-20230715")
At that point the project inputs and simulation registry are stored. You can then decide whether to:
call
model.run()immediatelydispatch
push_simulations()directly with custom worker argumentsdrain claims later with
pull_simulations()
This pattern is useful when generating receptors programmatically before handing off to a long-running workflow.
When to use Python vs the CLI#
Prefer the Python API when:
iterating in a notebook
generating receptors programmatically
you want direct access to model collections and output objects after a run
Prefer the CLI when:
the project already lives on disk with a config.yaml
launching workers from batch scripts or container entrypoints
you want a clean shell boundary around registration, status, and serving