Skip to content

Commit

Permalink
remove profiles and grids
Browse files Browse the repository at this point in the history
  • Loading branch information
chraibi committed Feb 25, 2024
1 parent addca02 commit 5e7e765
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 367 deletions.
20 changes: 10 additions & 10 deletions app.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Module Name: Jupedsim
"""Motivation model with jupedsim.
Description: This module contains functions for visualizing and simulating data.
Author: Mohcine Chraibi
Date: August 11, 2023
Expand Down Expand Up @@ -34,7 +34,7 @@


def read_data(output_file: str) -> pd.DataFrame:
"""reading data from csv file.
"""Read data from csv file.
Args:
output_file : path to csv file
Expand All @@ -53,7 +53,7 @@ def read_data(output_file: str) -> pd.DataFrame:


def set_color_and_size(data_df: pd.DataFrame) -> Tuple[str, List[float]]:
"""setting color and size with help of trajectory data.
"""Set color and size with help of trajectory data.
Args:
data_df (_type_): DataFrame containing trajectory data
Expand Down Expand Up @@ -97,7 +97,7 @@ def update_fig_layout(


def add_polygons_to_fig(fig: Figure, polygons: Dict[int, List[List[float]]]) -> None:
"""adding polygons to figure
"""Add polygons to figure.
Args:
fig (_type_): Plotly figure
Expand All @@ -117,7 +117,7 @@ def add_polygons_to_fig(fig: Figure, polygons: Dict[int, List[List[float]]]) ->


def customize_fig(fig: Figure) -> None:
"""Customize the appearance and layout of the Plotly figure
"""Customize the appearance and layout of the Plotly figure.
Args:
fig (_type_): Plotly figure
Expand All @@ -131,7 +131,7 @@ def customize_fig(fig: Figure) -> None:


def moving_trajectories(config_file: str, output_file: str) -> None:
"""Generate moving trajectories based on simulation
"""Generate moving trajectories based on simulation.
Args:
config_file (_type_): JSON file
Expand Down Expand Up @@ -251,7 +251,7 @@ def calculate_heatmap_values(
polygons: Dict[int, List[List[float]]],
) -> Tuple[npt.NDArray[Any], npt.NDArray[Any], npt.NDArray[Any]]:
"""
Calculate heatmap values using statistical binning
Calculate heatmap values using statistical binning.
Args:
position_x: Array of X positions.
Expand Down Expand Up @@ -342,7 +342,7 @@ def customize_fig_layout(fig: Figure) -> None:


def load_json(filename: p.Path) -> Any:
"""load json file"""
"""Load json file."""

try:
with open(filename, "r", encoding="utf-8") as file:
Expand All @@ -354,7 +354,7 @@ def load_json(filename: p.Path) -> Any:


def save_json(output: p.Path, data: Dict[str, Any]) -> None:
"""save data in json file"""
"""Save data in json file."""
with open(output, "w", encoding="utf-8") as file:
json.dump(data, file, indent=4)

Expand Down
109 changes: 12 additions & 97 deletions simulation.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
"""
Simulation model using jpscore API
"""
import contextlib
"""Simulation model using jpscore API."""

# Copyright © 2012-2022 Forschungszentrum Jülich GmbH
# SPDX-License-Identifier: LGPL-3.0-or-later

import contextlib
import json
import pathlib
import sys
Expand All @@ -17,28 +16,21 @@
from jupedsim.serialization import JpsCoreStyleTrajectoryWriter

from src import motivation_model as mm
from src import profiles as pp
from src.inifile_parser import (
is_motivation_active,
parse_motivation_parameter,
parse_motivation_strategy,
parse_velocity_init_parameters,
parse_accessible_areas,
parse_destinations,
parse_distribution_polygons,
parse_fps,
parse_grid_max_time_gap,
parse_grid_max_v0,
parse_grid_min_time_gap,
parse_grid_min_v0,
parse_grid_step_v0,
parse_grid_time_gap_step,
parse_motivation_doors,
parse_motivation_parameter,
parse_motivation_strategy,
parse_normal_time_gap,
parse_normal_v_0,
parse_number_agents,
parse_simulation_time,
parse_time_step,
parse_velocity_init_parameters,
parse_way_points,
)
from src.logger_config import init_logger, log_debug, log_error, log_info
Expand Down Expand Up @@ -73,8 +65,8 @@ def profile_function(name: str) -> Iterator[None]:

def init_simulation(
_data: Dict[str, Any], _time_step: float
) -> Tuple[Any, pp.ParameterGrid, mm.MotivationModel]:
"""Initialise geometry and parameter profiles.
) -> Tuple[Any, mm.MotivationModel]:
"""Initialise geometry.
:param data:
:type data: str
Expand All @@ -90,26 +82,6 @@ def init_simulation(
max_value = parse_motivation_parameter(data, "max_value")

accessible_areas = parse_accessible_areas(_data)

grid = pp.ParameterGrid(
min_v_0=parse_grid_min_v0(_data),
max_v_0=parse_grid_max_v0(_data),
v_0_step=parse_grid_step_v0(_data),
min_time_gap=parse_grid_min_time_gap(_data),
max_time_gap=parse_grid_max_time_gap(_data),
time_gap_step=parse_grid_time_gap_step(_data),
)

velocity_profiles = grid.velocity_profiles
parameter_profiles: Dict[int, List[float]] = {}
for velocity_profile in velocity_profiles:
parameter_profiles[velocity_profile.number] = [
velocity_profile.time_gap,
velocity_profile.tau,
velocity_profile.v_0,
velocity_profile.radius,
]

geometry = build_geometry(accessible_areas)
# areas = build_areas(destinations, labels)
a_ped, d_ped, a_wall, d_wall = parse_velocity_init_parameters(_data)
Expand All @@ -121,7 +93,6 @@ def init_simulation(
}
model = build_velocity_model(
init_parameters,
parameter_profiles=parameter_profiles,
)

simulation = jps.Simulation(model=model, geometry=geometry, dt=_time_step)
Expand Down Expand Up @@ -157,49 +128,12 @@ def init_simulation(
)
motivation_model.print_details()
log_info("Init simulation done")
return simulation, grid, motivation_model


def update_profiles(
simulation: Any,
grid: pp.ParameterGrid,
motivation_model: mm.MotivationModel,
file_handle: _io.TextIOWrapper,
) -> None:
"""Switch profile of pedestrian depending on its motivation."""

agents = simulation.agents()
for agent in agents:
position = agent.position
actual_profile = agent.profile_id
(
new_profile,
motivation_i,
v_0,
time_gap,
distance,
) = motivation_model.get_profile_number(
position, simulation.agent_count(), grid
)
try:
simulation.switch_agent_profile(agent_id=agent.id, profile_id=new_profile)
write_value_to_file(
file_handle,
f"{position[0]} {position[1]} {motivation_i} {v_0} {time_gap} {distance}",
)
except RuntimeError:
# pass
log_error(
f"""Can not change Profile of Agent {agent.id}
to Profile={actual_profile} at
Iteration={simulation.iteration_count()}."""
)
return simulation, motivation_model


def run_simulation(
simulation: Any,
writer: Any,
grid: pp.ParameterGrid,
motivation_model: mm.MotivationModel,
_simulation_time: float,
) -> None:
Expand All @@ -221,28 +155,9 @@ def run_simulation(
):
simulation.iterate()

if motivation_model.active and simulation.iteration_count() % 100 == 0:
with profile_function("update profiles"):
# time_1 = time.perf_counter_ns()
update_profiles(simulation, grid, motivation_model, file_handle)
# time_2 = time.perf_counter_ns()
# delta = time_2 - time_1
# deltas.append(delta / 1000000)
# print(
# f"{simulation.agent_count()}: {simulation.iteration_count()}: {delta=}"
# )

if simulation.iteration_count() % 10 == 0:
writer.write_iteration_state(simulation)

# profiler.disable()
# stats = pstats.Stats(profiler)
# stats.dump_stats("profile_stats.prof") # Save to file
# if deltas:
# print(
# f"{np.min(deltas)=}, {np.max(deltas)=}, {np.mean(deltas)=}, {np.median(deltas)=}"
# )


def main(
_number_agents: int,
Expand All @@ -261,14 +176,14 @@ def main(
:returns:
"""
simulation, grid, motivation_model = init_simulation(_data, _time_step)
simulation, motivation_model = init_simulation(_data, _time_step)
way_points = parse_way_points(_data)
destinations_dict = parse_destinations(_data)
destinations = list(destinations_dict.values())
journey_id = init_journey(simulation, way_points, destinations[0])

agent_parameters = init_velocity_agent_parameters(
phi_x=1, phi_y=0, journey=journey_id, profile=1
phi_x=1, phi_y=0, journey=journey_id
)
distribution_polygons = parse_distribution_polygons(_data)
positions = []
Expand All @@ -293,7 +208,7 @@ def main(
log_info(f"Running simulation for {len(ped_ids)} agents:")
writer = JpsCoreStyleTrajectoryWriter(_trajectory_path)
writer.begin_writing(_fps)
run_simulation(simulation, writer, grid, motivation_model, _simulation_time)
run_simulation(simulation, writer, motivation_model, _simulation_time)
writer.end_writing()
log_info(f"Simulation completed after {simulation.iteration_count()} iterations")
log_info(
Expand Down
33 changes: 2 additions & 31 deletions src/inifile_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

def parse_destinations(json_data: Dict[str, Any]) -> Dict[int, List[List[Point]]]:
"""
Parses the 'destinations' object from a JSON string into a Python dictionary.
Parse the 'destinations' object from a JSON string into a Python dictionary.
Args:
json_data: A dict containing JSON data with a 'destinations' object.
Expand All @@ -37,35 +37,8 @@ def parse_destinations(json_data: Dict[str, Any]) -> Dict[int, List[List[Point]]
return _destinations


def parse_velocity_model_parameter_profiles(
json_data: Dict[str, Any]
) -> Dict[int, List[float]]:
"""
Parse the 'velocity_model_parameter_profiles' object
from a JSON string into a Python dictionary.
Args:
json_data: A dict containing JSON data with a
'velocity_model_parameter_profiles' object.
Returns:
A dictionary with the parsed 'velocity_model_parameter_profiles' object. The dictionary maps
ID (int) to lists of floating-point numbers.
"""

_profiles: Dict[int, List[float]] = {}
for profile in json_data["velocity_model_parameter_profiles"]:
id_str = profile["id"]
time_gap = profile["time_gap"]
tau = profile["tau"]
v_0 = profile["v0"]
radius = profile["radius"]
_profiles[int(id_str)] = [time_gap, tau, v_0, radius]
return _profiles


def parse_velocity_init_parameters(
json_data: Dict[str, Any]
json_data: Dict[str, Any],
) -> Tuple[float, float, float, float]:
"""Parse init parameters for velocity model.
Expand Down Expand Up @@ -398,7 +371,6 @@ def print_obj(obj: Dict[int, Any], name: str) -> None:
destinations = parse_destinations(data)
distribution_polygons = parse_distribution_polygons(data)
way_points = parse_way_points(data)
profiles = parse_velocity_model_parameter_profiles(data)
version = data["version"]
fps = parse_fps(data)
time_step = parse_time_step(data)
Expand Down Expand Up @@ -431,7 +403,6 @@ def print_obj(obj: Dict[int, Any], name: str) -> None:
print_obj(destinations, "destination")
print_obj(motivation_doors, "motivation_doors")
print_obj(distribution_polygons, "distribution polygon")
print_obj(profiles, "profile")
print(f"{measurement_points=}")
print(f"init_velocity_model: {init_velocity}")
print(f"{way_points=}")
Expand Down
31 changes: 2 additions & 29 deletions src/motivation_model.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
"""
Module for motivational model
"""
"""Module for motivational model."""

import random
from dataclasses import dataclass
from typing import Any, Optional, Tuple, TypeAlias

import numpy as np

from .logger_config import log_debug
from .profiles import ParameterGrid

Point: TypeAlias = Tuple[float, float]

Expand Down Expand Up @@ -128,28 +126,3 @@ def calculate_motivation_state(self, motivation_i: float) -> Tuple[float, float]
time_gap_new = time_gap / (1 + motivation_i)

return v_0_new, time_gap_new

def get_profile_number(
self, position: Point, number_agents_in_simulation: int, grid: ParameterGrid
) -> Tuple[int, float, float, float, float]:
"""Calculate the profile num from grid based on motivation related (v0,T)."""

def calculate_distance():
x_door = 0.5 * (self.door_point1[0] + self.door_point2[0])
y_door = 0.5 * (self.door_point1[1] + self.door_point2[1])
door = [x_door, y_door]
distance = (
(position[0] - door[0]) ** 2 + (position[1] - door[1]) ** 2
) ** 0.5
return distance

distance = calculate_distance()
params = {
"distance": distance,
"number_agents_in_simulation": number_agents_in_simulation,
}
motivation_i = self.motivation_strategy.motivation(params)

v_0, time_gap = self.calculate_motivation_state(motivation_i)
number = int(grid.get_profile_number(v_0_i=v_0, time_gap_i=time_gap))
return number, motivation_i, v_0, time_gap, distance
Loading

0 comments on commit 5e7e765

Please sign in to comment.