An expectancy-value-payoff (EVP) motivation model for pedestrian dynamics, implemented on top of JuPedSim.
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtThe full pipeline runs in three stages. All commands are run from
the repository root (simulation/).
python scripts/run_all_scenario_analyses.pyWhat it does (≈ 40 min):
- Reads
scripts/run_coordination_scenarios.pywhich defines:BASE_MODELS = ["P", "V", "SE", "PVE", "BASE_MODEL"]NUMBER_AGENTS_VALUES = [40, 80]SEEDS = [101, 102, ..., 110]
- For each
(N, seed)combination, generates a per-seed config by copying the base JSON (e.g.files/base_PVE.json) and overwritingmotivation_parameters.seed. The same seed is used across all models so that initial positions and value assignments are identical — this is the paired design. - Runs
simulation.pyonce per(model, seed), producing:base_{MODEL}_seed{SEED}_{MODE}_{TIMESTAMP}.sqlite— trajectory..._motivation.csv— per-agent per-frame motivation values
- For each seed, calls the four analysis scripts with explicit
--input MODEL=<file>overrides and a--tagsuffix:
| Analysis script | What it computes | Output |
|---|---|---|
scripts/final_rank_analysis.py |
Distance-to-door rank at last frame + mean Voronoi area per agent | final_rank_details_*_seed{N}.csv + scatter plots |
scripts/coordination_number_analysis.py |
Delaunay neighbor count per agent per frame | coordination_number_details_*_seed{N}.csv + histograms |
scripts/motivation_heatmap_analysis.py |
Spatial mean-motivation grid | heatmap PNGs |
scripts/voronoi_density_analysis.py |
Voronoi density in measurement area over time | voronoi_density_details_*_seed{N}.csv + time series |
Outputs go to files/coordination_scenarios/agents_{N}_open_100/.
python scripts/aggregate_seeds.pyWhat it does (seconds):
- Walks
files/coordination_scenarios/*/and reads all seed-tagged detail CSVs from Stage 1. - Computes per-seed summary scalars:
- Rank–area: Spearman ρ, OLS slope, tail ratio
- Voronoi density: mean, std, fraction of time above threshold
- Coordination number: mean, std, mode
- Runs paired Wilcoxon signed-rank tests with Cliff's δ effect sizes comparing PVE vs BASE_MODEL.
- Produces band plots (median + IQR across 10 seeds).
Outputs go to files/coordination_scenarios/_aggregated/:
| File | Contents |
|---|---|
seed_summary.csv |
One row per (seed, model, observable, scalar) |
tests.csv |
Paired Wilcoxon p-values and Cliff's δ per comparison |
rank_area_band_*.png |
Rank–area median + IQR bands |
voronoi_density_band_*.png |
Density time-series bands |
coordination_number_band_*.png |
Coordination number histogram bands |
python scripts/experimental_rank_area.pyWhat it does (≈ 10 min):
- Reads the CROMA
.txttrajectory files from../trajectories_croma/. - For each experimental run, computes crossing order at the door (first frame where y ≥ 20) as the experimental rank.
- Computes per-agent mean Voronoi area using PedPy with the CROMA corridor geometry.
- Writes per-scenario CSVs + summary scalars (Spearman ρ, slope, tail ratio) and comparison plots.
Outputs go to files/experimental_rank_area_results/.
The expectancy, value, payoff, motivation, and parameter-mapping plots shown in the paper are produced headlessly by:
python scripts/plot_evp_schematics.py # default: N=80, seed=101, base_PVE.jsonThis writes expectancy.pdf, value.pdf, payoff.pdf,
motivation.pdf, and parameter_mappings.pdf directly into
../motivation-for-springer/figures/. Internally it instantiates an
EVPStrategy from src/motivation_model.py and calls its plot()
method plus motivation_mapping.plot_parameter_mappings().
Only the figures that are actually rendered in the paper are listed
below. Three blocks (coordination-number bands, Voronoi density bands,
N=40 final-rank scatter) are wrapped in \iffalse in the manuscript
and are therefore not regenerated; the underlying analysis scripts
still produce the data, but the PDFs are not copied into the paper.
| Figure (paper) | Output filename(s) | Produced by |
|---|---|---|
Fig 1 fig:evc_components (expectancy, value, payoff, motivation) |
expectancy.pdf, value.pdf, payoff.pdf, motivation.pdf |
scripts/plot_evp_schematics.py |
Fig 2 fig:rank-area-bands |
rank_area_band_agents_{40,80}_open_100.png |
scripts/aggregate_seeds.py (Stage 2) |
Fig 3 fig:motivation-heatmaps-scenarios |
agents_80_open_100/motivation_heatmap_results/motivation_heatmap_models_agents_80_open_100.png |
scripts/motivation_heatmap_analysis.py (Stage 1, per-seed; copy seed-101 output to the un-suffixed paper name) |
Fig 4a fig:sim-trajectories-uniform (sim trajectories, single color) |
simulation_trajectories_5panel_uniform.png |
scripts/plot_simulation_trajectories.py |
Fig 4b fig:sim-trajectories (sim trajectories, motivation-colored) |
simulation_trajectories_5panel_motivation.png |
scripts/plot_simulation_trajectories.py |
Fig 5 fig:croma-trajectories (CROMA experimental trajectories, 1×4) |
croma_trajectories_4panel.png |
scripts/plot_experimental_trajectories.py |
Fig 6 fig:croma-rank-area (CROMA rank-area nM/hM) |
croma_rank_area_{nM,hM}.png |
scripts/experimental_rank_area.py |
Fig A.1 fig:parameter-mappings |
parameter_mappings.pdf |
scripts/plot_evp_schematics.py |
Fig A.2 fig:final-rank-scenarios (N=80 only) |
agents_80_open_100/final_rank_results/final_rank_vs_area_{se,v,p,pve,base_model}_agents_80_open_100.pdf |
scripts/final_rank_analysis.py (Stage 1, per-seed; copy seed-101 outputs to the un-suffixed paper names) |
The trajectory-panel and schematic scripts are standalone and read directly from existing simulation / CROMA outputs (no full pipeline rerun required):
# Schematics: expectancy/value/payoff/motivation/parameter_mappings (Fig 1, A.1)
python scripts/plot_evp_schematics.py
# CROMA 4-panel (Fig 5)
python scripts/plot_experimental_trajectories.py
# Simulation 5-panel × 2 variants (Fig 4a, 4b)
python scripts/plot_simulation_trajectories.py --seed 101For Fig 3 and Fig A.2 the per-seed PDFs/PNGs in
files/coordination_scenarios/agents_{N}_open_100/.../ carry a
_seedNNN suffix; copy seed 101 to the un-suffixed paper name when
syncing figures (the paper convention is to show a single
representative seed):
cp files/coordination_scenarios/agents_80_open_100/motivation_heatmap_results/motivation_heatmap_models_agents_80_open_100_seed101.png \
../motivation-for-springer/figures/agents_80_open_100/motivation_heatmap_results/motivation_heatmap_models_agents_80_open_100.png
for m in se v p pve base_model; do
cp files/coordination_scenarios/agents_80_open_100/final_rank_results/final_rank_vs_area_${m}_agents_80_open_100_seed101.pdf \
../motivation-for-springer/figures/agents_80_open_100/final_rank_results/final_rank_vs_area_${m}_agents_80_open_100.pdf
doneAll simulation parameters are in files/base_{MODEL}.json. Key settings:
| Parameter | Location in JSON | Paper value |
|---|---|---|
| Motivation mode | motivation_parameters.motivation_mode |
PVE / BASE_MODEL / P / V / SE |
| Auto-k logistic | motivation_parameters.use_manual_logistic_k |
false |
| Seeds | motivation_parameters.seed |
101–110 (set by pipeline) |
| Number of agents | simulation_parameters.number_agents |
40 or 80 |
| Door open time | simulation_parameters.open_door_time |
100 (> sim time → closed) |
| Simulation time | simulation_parameters.simulation_time |
90 s |
simulation/
├── simulation.py Main simulation runner (JuPedSim)
├── app.py Streamlit interactive UI
├── files/
│ ├── base.json Template configuration
│ ├── base_{MODEL}.json Per-model configs (P, V, SE, PVE, BASE_MODEL)
│ ├── coordination_scenarios/ Simulation outputs + analysis results
│ └── experimental_rank_area_results/
├── scripts/
│ ├── run_coordination_scenarios.py Config generation + seed definitions
│ ├── run_all_scenario_analyses.py Full pipeline runner (Stage 1)
│ ├── aggregate_seeds.py Cross-seed aggregation (Stage 2)
│ ├── experimental_rank_area.py CROMA analysis (Stage 3)
│ ├── final_rank_analysis.py Rank–area per-seed analysis
│ ├── coordination_number_analysis.py Coordination number per-seed analysis
│ ├── motivation_heatmap_analysis.py Spatial motivation heatmaps
│ ├── voronoi_density_analysis.py Voronoi density time series
│ ├── plot_experimental_trajectories.py CROMA trajectories 1×4 panel (Fig 7)
│ └── plot_simulation_trajectories.py Simulation 5-panel × 2 variants (Fig 6)
├── src/
│ ├── motivation_model.py EVPStrategy: expectancy-value-payoff model
│ ├── motivation_mapping.py Logistic motivation-to-parameter mapping
│ ├── coordination_number.py Delaunay coordination numbers
│ ├── utilities.py Voronoi area, rank, crossing-order utilities
│ └── ...
└── tests/
streamlit run app.pypython simulation.py --inifile files/base_PVE.json --output-dir output/MIT