Skip to content

Commit

Permalink
feat!: scenario path management (#61)
Browse files Browse the repository at this point in the history
* new SimulationScenario class replacing SimulationParameters, manages scenario folders and data
* changed signature of functions to accept a scenario folder path. Scenario path is no longer computed from the model code and scenario name
* BREAKING CHANGE: now provide path to the scenario folder instead of path to the simulation parameters to run a simulation
  • Loading branch information
leo-desbureaux-tellae authored Jul 28, 2022
1 parent 068f587 commit ccc6bb2
Show file tree
Hide file tree
Showing 21 changed files with 252 additions and 331 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,12 @@ python3 main.py -e
### Usage

Once the data is prepared, a scenario can be run from the project
root by running main.py with the path to the scenario parameters.
root by running main.py with the path to the scenario folder.

Run one of the example scenarios, for instance:

```bash
python3 main.py data/models/SB_VS/example_nantes/inputs/Params.json
python3 main.py data/models/SB_VS/example_nantes/
```

You will see the progression of the simulation with the logs that
Expand Down
6 changes: 3 additions & 3 deletions docs/run/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,19 @@ Run
***

Example scenarios can be run like any other scenario by running main.py
with the path to the parameters file. For instance:
with the path to the scenario folder. For instance:

.. code-block:: bash
python3 main.py data/models/SB_VS/example_nantes/inputs/Params.json
python3 main.py data/models/SB_VS/example_nantes/
You will then see the simulation logs display in the console, until the run finishes.
If you find the logs too verbose, you can set the logging level to a higher level
with the ``-l`` option (see simulation_logging.py for more information):

.. code-block:: bash
python3 main.py -l 20 data/models/SB_VS/example_nantes/inputs/Params.json
python3 main.py -l 20 data/models/SB_VS/example_nantes/
*******
Outputs
Expand Down
8 changes: 4 additions & 4 deletions docs/run/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Usage
Data preparation
****************

Simulation scenarios are launched from a file that contains
Simulation scenarios are launched from a parameter file that contains
global parameters of the simulation.

Simulation data must be placed in data/models/<model_code>/<scenario_name>/inputs
Expand All @@ -22,11 +22,11 @@ Once you have setup your execution environment (either on your device or with Do
and your simulation data (see :ref:`inout`), you can run your scenario.

Simulations are run by executing the script main.py from the project root
with a path to the parameters file of the scenario. For instance:
with the path to your scenario folder. For instance:

.. code-block:: bash
python3 main.py data/models/SB_VS/my_scenario/inputs/Params.json
python3 main.py data/models/SB_VS/my_scenario/
For more information about the options of main.py use the ``-h`` (or ``--help``) option:

Expand All @@ -43,7 +43,7 @@ With Docker, this can be done in detached mode with
.. code-block:: bash
docker run -d -v "$(pwd)":/starling_dir/ --name container_name starling\
bash -c "python3 main.py data/models/SB_VS/my_scenario/inputs/Params.json"
bash -c "python3 main.py data/models/SB_VS/my_scenario/"
or in interactive mode with

Expand Down
2 changes: 1 addition & 1 deletion starling_sim/basemodel/agent/operators/operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ def init_zone(self, zone_polygon):

if isinstance(zone_polygon, str):
filepath = scenario_agent_input_filepath(
self.sim.parameters["code"], self.sim.parameters["scenario"], zone_polygon
self.sim.scenario.scenario_folder, zone_polygon
)
geojson = json_load(filepath)
service_zone = geopandas_polygon_from_points(
Expand Down
4 changes: 2 additions & 2 deletions starling_sim/basemodel/algorithms/pal_zhang_GCH.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ def compute_station_variation(self, station_id):

index = self.start_times.index(self.current_time)
if index == len(self.start_times) - 1:
horizon = self.sim.parameters["limit"]
horizon = self.sim.scenario["limit"]
else:
horizon = self.start_times[index + 1]

Expand Down Expand Up @@ -366,7 +366,7 @@ def append_depot_to_planning(self):
def init_demand_dict(self):

features = self.sim.dynamicInput.feature_list_from_file(
self.sim.parameters["dynamic_input_file"]
self.sim.scenario["dynamic_input_file"]
)
self.sim.dynamicInput.pre_process_position_coordinates(features)
demand_dict = {station: [] for station in self.operator.stations.keys()}
Expand Down
8 changes: 4 additions & 4 deletions starling_sim/basemodel/environment/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class Environment:
Describes an environment in which the simulation will take place
"""

def __init__(self, parameters, network="osm"):
def __init__(self, scenario, network="osm"):
"""
Initialization of the environment, without import of data structures.
Expand All @@ -21,11 +21,11 @@ def __init__(self, parameters, network="osm"):
self.topologies = {}

# get the topologies dict
topologies_dict = parameters["topologies"]
topologies_dict = scenario["topologies"]

# get the 'store_paths' parameter
if "store_paths" in parameters:
store_paths = parameters["store_paths"]
if "store_paths" in scenario:
store_paths = scenario["store_paths"]
else:
store_paths = False

Expand Down
19 changes: 8 additions & 11 deletions starling_sim/basemodel/input/dynamic_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def setup(self, simulation_model):
# set the attribute of dynamic features

self.dynamic_feature_list = self.feature_list_from_file(
self.sim.parameters["dynamic_input_file"]
self.sim.scenario["dynamic_input_file"]
)

# sort list according to origin times
Expand All @@ -64,7 +64,7 @@ def setup(self, simulation_model):
)

# get the list of static features (present at the start of the simulation)
init_files = self.sim.parameters["init_input_file"]
init_files = self.sim.scenario["init_input_file"]

# if there are several files, concatenate their feature lists
if isinstance(init_files, list):
Expand Down Expand Up @@ -135,10 +135,10 @@ def play_dynamic_input_(self):

# see if an offset should be applied to the input origin time
if (
"early_dynamic_input" in self.sim.parameters
and self.sim.parameters["early_dynamic_input"]
"early_dynamic_input" in self.sim.scenario
and self.sim.scenario["early_dynamic_input"]
):
early_input_time_offset = self.sim.parameters["early_dynamic_input"]
early_input_time_offset = self.sim.scenario["early_dynamic_input"]
else:
early_input_time_offset = 0

Expand Down Expand Up @@ -283,10 +283,7 @@ def feature_list_from_file(self, filename):
return []

# get the path to the input file
parameters = self.sim.parameters
filepath = scenario_agent_input_filepath(
parameters["code"], parameters["scenario"], filename
)
filepath = scenario_agent_input_filepath(self.sim.scenario.scenario_folder, filename)

# read the dict contained in input file
try:
Expand Down Expand Up @@ -315,7 +312,7 @@ def feature_list_from_file(self, filename):

def make_demand_static(self):

if "make_static" in self.sim.parameters and self.sim.parameters["make_static"] in [
if "make_static" in self.sim.scenario and self.sim.scenario["make_static"] in [
"all",
"prebooked",
"prebooked_only",
Expand All @@ -325,7 +322,7 @@ def make_demand_static(self):
# also add the agents of dynamic input that are prebooked
dynamic_features = []

make_static = self.sim.parameters["make_static"]
make_static = self.sim.scenario["make_static"]

for feature in self.dynamic_feature_list:
properties = feature["properties"]
Expand Down
2 changes: 1 addition & 1 deletion starling_sim/basemodel/output/feature_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ def get_element_line_string(geojson_output, element):

# get the list of route localisations and timestamps
route_positions, route_timestamps = route_localisations(
event, geojson_output.sim.parameters["limit"], geojson_output.graphs[mode]
event, geojson_output.sim.scenario["limit"], geojson_output.graphs[mode]
)

# add it to the agent's lists
Expand Down
21 changes: 9 additions & 12 deletions starling_sim/basemodel/output/output_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,15 @@ def setup(self, simulation_model):
self.sim = simulation_model

# get output folder
output_folder = simulation_model.parameters["output_folder"]
output_folder = simulation_model.scenario.outputs_folder

# get scenario
scenario = simulation_model.parameters["scenario"]
scenario = simulation_model.scenario.name

# setup kpi outputs

self.setup_kpi_output()

if not os.path.exists(output_folder):
os.mkdir(output_folder)

for kpi_output in self.kpi_outputs:

# build the kpi output filename
Expand Down Expand Up @@ -139,19 +136,19 @@ def extract_simulation(self, simulation_model):
"""

# traces output
if simulation_model.parameters["traces_output"]:
if simulation_model.scenario["traces_output"]:
try:
self.generate_trace_output(simulation_model)
except:
logging.warning(self.GENERATION_ERROR_FORMAT.format("traces"))

# kpi output
if simulation_model.parameters["kpi_output"]:
if simulation_model.scenario["kpi_output"]:
self.generate_kpi_output(simulation_model)

# geojson output

if simulation_model.parameters["visualisation_output"]:
if simulation_model.scenario["visualisation_output"]:
try:
self.generate_geojson_output(simulation_model)
except:
Expand Down Expand Up @@ -192,9 +189,9 @@ def generate_trace_output(self, simulation_model):
"""

# get the scenario information and outfile
scenario = simulation_model.parameters["scenario"]
model_code = simulation_model.parameters["code"]
output_folder = simulation_model.parameters["output_folder"]
scenario = simulation_model.scenario.name
model_code = simulation_model.scenario.model
output_folder = simulation_model.scenario.outputs_folder
filepath = output_folder + config["traces_format"].format(scenario=scenario)

# open the trace file in write mode
Expand Down Expand Up @@ -229,7 +226,7 @@ def generate_run_summary(self, simulation_model):
:param simulation_model:
"""
filepath = simulation_model.parameters["output_folder"] + RUN_SUMMARY_FILENAME
filepath = simulation_model.scenario.outputs_folder + RUN_SUMMARY_FILENAME

# add run summary to output files
self.sim.outputFactory.new_output_file(filepath, "application/json", content="run_summary")
Expand Down
3 changes: 0 additions & 3 deletions starling_sim/basemodel/parameters/__init__.py

This file was deleted.

Loading

0 comments on commit ccc6bb2

Please sign in to comment.