Concepts#

Three objects carry state through jupedsim-scenarios. Knowing which one you are holding — and what mutating it does — prevents most surprises.

Lifecycle#

zip / json / directory
         │
         ▼  load_scenario(...)
┌──────────────────┐
│     Scenario     │  mutable; .copy() to branch
└──────────────────┘
         │
         ▼  run_scenario(scenario, seed=...)
┌──────────────────┐
│  ScenarioResult  │  owns a temp sqlite; call .cleanup()
└──────────────────┘
         │
         ▼  .trajectory_dataframe()  /  .sqlite_file
     pandas / pedpy analysis

For parameter studies:

    base : Scenario  ──►  run_sweep(base, axes=..., apply=..., seeds=...)
                                    │
                                    ▼
                              ┌──────────────┐
                              │ SweepResult  │  .save(...) / load(...)
                              └──────────────┘

Scenario — the mutable plan#

A Scenario is the in-memory representation of one simulation setup: geometry, agents, journeys, solver settings, seed, and time limits.

It is mutable. Every add_* / remove_* / set_* call, and every direct attribute assignment, changes the instance in place:

base = load_scenario("bottleneck.zip")
base.seed = 99             # base is now permanently at seed=99

If you want to keep the original intact — and you almost always do once you start sweeping or comparing variants — call .copy() first and edit the clone:

trial = base.copy()
trial.seed = 99
trial.max_simulation_time = 60
# base is untouched

run_sweep() does this for you per trial. The copy-first discipline only matters when you assemble variants by hand. See How do I sweep over scenario shapes that axes / apply can’t express? for the worked pattern.

Inspecting the plan#

scenario.plot() draws the walkable area with labelled distributions, exits, zones, and checkpoints. Two arguments turn it into a before/after view of a run:

  • show_journeys=True (the default) overlays each journey’s route as curved arrows in stage order. Both schema versions are read, so current web-editor exports (journeys_v2) show routes too.

  • trajectories= takes a ScenarioResult (or a pedpy TrajectoryData) and draws the agent paths from a completed run on top of the plan. Use show_trajectories=False to force it off.

result = run_scenario(scenario, seed=42)
scenario.plot(show_journeys=True, trajectories=result)

See Visualisation for the full tour.

ScenarioResult — the run output#

run_scenario() returns a ScenarioResult. It carries summary metrics (evacuation_time, agents_evacuated, frame_rate, …) and owns a temporary SQLite trajectory file written by the simulator.

Two things to remember:

  • trajectory_dataframe() materializes the trajectory as a pandas DataFrame compatible with pedpy.

  • visualise() returns an interactive plotly animation of the run — agents coloured by speed, with a play button and time slider. Pass save_path="run.html" to write a self-contained file.

  • cleanup() deletes the temp sqlite. Call it when you are done, or wrap your run in a try / finally block. The file does not vanish on garbage collection.

result = run_scenario(scenario, seed=42)
try:
    df = result.trajectory_dataframe()
    # ...analysis...
finally:
    result.cleanup()

SweepResult — the persisted study#

run_sweep() and run_sweep_from_factory() return a SweepResult. It is the artifact you save, re-load, and analyze across sessions.

  • to_dataframe() returns one row per trial: parameter values, metrics, sqlite path.

  • save(path) / SweepResult.load(path) round-trip a sweep, including the per-trial trajectory databases. Useful for long studies that you want to analyze separately.

  • cleanup() removes all per-trial temp files.

See How do I persist a sweep and reload it later? for the save/reload pattern.

Where each object lives#

Object

Lives in

Disk footprint

Scenario

Python memory only

None until you save

ScenarioResult

Python + temp sqlite

One trajectory db

SweepResult

Python + temp dir

One sqlite per trial

Next#