Skip to content

Commit

Permalink
Merge branch 'dev' into feature/pickle_mode
Browse files Browse the repository at this point in the history
  • Loading branch information
stefan.schirmeister committed Sep 25, 2024
2 parents 67552ee + 7b4bbda commit f15fae9
Show file tree
Hide file tree
Showing 14 changed files with 815 additions and 106 deletions.
10 changes: 6 additions & 4 deletions data/examples/simba.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ scenario_name = example
##### Paths #####
### Input and output files and paths ###
# Input file containing trip information (required)
input_schedule = data/examples/trips_example.csv
schedule_path = data/examples/trips_example.csv
# Output files are stored here (defaults to: data/sim_outputs)
# Attention: In Windows the path-length is limited to 256 characters!
# Deactivate storage of output by setting output_directory = null
output_directory = data/output/
output_path = data/output/
# Electrified stations (required)
electrified_stations_path = data/examples/electrified_stations.json
# Vehicle types (defaults to: ./data/examples/vehicle_types.json)
Expand All @@ -23,11 +23,11 @@ outside_temperature_over_day_path = data/examples/default_temp_winter.csv
# (Optional: needed if mileage in vehicle types not constant)
level_of_loading_over_day_path = data/examples/default_level_of_loading_over_day.csv
# Path to configuration file for the station optimization. Only needed for mode "station_optimization"
optimizer_config = data/examples/default_optimizer.cfg
optimizer_config_path = data/examples/default_optimizer.cfg
# Cost parameters (needed if cost_calculation flag is set to true, see Flag section below)
cost_parameters_path = data/examples/cost_params.json
# Path to rotation filter
rotation_filter = data/examples/rotation_filter.csv
rotation_filter_path = data/examples/rotation_filter.csv

##### Modes #####
### Specify how you want to simulate the scenario ###
Expand All @@ -54,6 +54,8 @@ check_rotation_consistency = false
skip_inconsistent_rotations = false
# Show plots for users to view, only used in mode report (default: false)
show_plots = false
# generate special plots in report mode (default: false)
extended_output_plots = false
# Rotation filter variable, options:
# "include": include only the rotations from file 'rotation_filter'
# "exclude": exclude the rotations from file 'rotation_filter' from the schedule
Expand Down
2 changes: 2 additions & 0 deletions docs/source/modes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,8 @@ To make use of this feature the parameters in the optimizer.cfg have to be set.
decision_tree_path = data/last_optimization.pickle
save_decision_tree = True

.. _optimizer_config:

Optimizer Configuration
###################################
The functionality of the optimizer is controlled through the optimizer.cfg specified in the simba.cfg used for calling SimBA.
Expand Down
5 changes: 4 additions & 1 deletion docs/source/simba_features.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,10 @@ Generate report

The generation of the report is implemented as a mode, that can be activated with the keyword "report" in modes (:ref:`report`). The report generates most of the output files. The report can be called any number of times e.g. mode = ["sim", "report", "neg_depb_to_oppb", "report", "service_optimization", "report"]. For each report, a sub-folder is created in the output directory (as defined in the :ref:`config`) named "report_[nr]" with the respective number.

The generation of the report can be modified using the flag "cost_calculation" in :ref:`config`. If this flag is set to true, each report will also generate the file "summary_vehicles_costs.csv".
The generation of the report can be modified using flags in :ref:`config`.

1. If ``cost_calculation`` is set, each report will also generate the file "summary_vehicles_costs.csv".
2. If ``extended_output_plots`` is set, more plots will be saved to "extended_plots" in the report directory. These plots include the number of active rotations over time, a distribution of charge types, histograms of rotation consumption and distance as well as station-specific power levels.

Default outputs
###############
Expand Down
21 changes: 16 additions & 5 deletions docs/source/simulation_parameters.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,19 @@ The example (data/simba.cfg) contains parameter descriptions which are explained
- Optional: no default given
- string
- scenario identifier, appended to output directory name and report file names
* - input_schedule
* - schedule_path
- Mandatory: no default given
- Path as string
- Input file containing :ref:`schedule` information
* - Output_directory
* - output_path
- Data/sim_outputs
- Path as string
- Output files are stored here; set to null to deactivate
* - electrified_stations_path
- ./data/examples/vehicle_types.json
- Path as string
- Path to Electrified stations data
* - vehicle_types
* - vehicle_types_path
- ./data/examples/vehicle_types.json
- Path as string
- Path to :ref:`vehicle_types`
Expand All @@ -60,10 +60,18 @@ The example (data/simba.cfg) contains parameter descriptions which are explained
- Optional: no default given
- Path as string
- Path to :ref:`level_of_loading`
* - cost_parameters_file
* - cost_parameters_path
- Optional: no default given
- Path as string
- Path to :ref:`cost_params`
* - optimizer_config_path
- Optional: no default given
- Path as string
- Path to station optimizer config :ref:`optimizer_config`
* - rotation_filter_path
- Optional: no default given
- Path as string
- Path to rotation filter json
* - mode
- ['sim', 'report']
- List of modes is any order in range of ['sim', 'neg_depb_to_oppb', 'neg_oppb_to_depb', 'service_optimization', 'report']
Expand Down Expand Up @@ -100,7 +108,10 @@ The example (data/simba.cfg) contains parameter descriptions which are explained
- Optional, no default given
- Path to pickle file
- Load schedule and scenario from this pickle file, expects load_pickle as first mode

* - extended_output_plots
- false
- Boolean
- If set, create additional plots when running :ref:`report` mode
* - strategy_deps
- balanced
- SpiceEV Strategies (greedy, balanced, peak_shaving, peak_load_windows, balanced_market)
Expand Down
27 changes: 12 additions & 15 deletions simba/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,30 +14,21 @@
dir_name = time_str + '_' + args.scenario_name
else:
dir_name = time_str
if args.output_directory is not None:
args.output_directory = Path(args.output_directory) / dir_name
if args.output_path is not None:
args.output_path = Path(args.output_path) / dir_name
# create subfolder for specific sim results with timestamp.
# if folder doesn't exist, create folder.
# needs to happen after set_options_from_config since
# args.output_directory can be overwritten by config
args.output_directory_input = args.output_directory / "input_data"
# args.output_path can be overwritten by config
args.output_directory_input = args.output_path / "input_data"
try:
args.output_directory_input.mkdir(parents=True, exist_ok=True)
except NotADirectoryError:
# can't create new directory (may be write protected): no output
args.output_directory = None
if args.output_directory is not None:
# copy input files to output to ensure reproducibility
copy_list = [args.config, args.electrified_stations_path, args.vehicle_types_path]
if "station_optimization" in args.mode:
copy_list.append(args.optimizer_config)

# only copy cost params if they exist
if args.cost_parameters_path is not None:
copy_list.append(args.cost_parameters_path)
for c_file in map(Path, copy_list):
shutil.copy(c_file, args.output_directory_input / c_file.name)

# copy basic input to output to ensure reproducibility
util.save_input_file(args.config, args)
util.save_version(args.output_directory_input / "program_version.txt")

util.setup_logging(args, time_str)
Expand All @@ -49,3 +40,9 @@
raise
finally:
logging.shutdown()
if args.zip_output and args.output_directory is not None and args.output_directory.exists():
# compress output directory after simulation
# generate <output_directory_name>.zip at location of original output directory
shutil.make_archive(args.output_directory, 'zip', args.output_directory)
# remove original output directory
shutil.rmtree(args.output_directory)
15 changes: 13 additions & 2 deletions simba/data_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,21 @@ def __init__(self):
# List of trip dictionaries containing trip information like arrival time and station
# departure time and station, distance and more
self.trip_data: [dict] = []
# Simulation arguments
self.args = None

def fill_with_args(self, args: argparse.Namespace) -> 'DataContainer':
""" Fill DataContainer with data from file_paths defined in args.
:param args: Arguments containing paths for input_schedule, vehicle_types_path,
:param args: Arguments containing paths for schedule_path, vehicle_types_path,
electrified_stations_path, cost_parameters_path, outside_temperature_over_day_path,
level_of_loading_over_day_path, station_data_path
:return: self
"""
self.args = args

return self.fill_with_paths(
trips_file_path=args.input_schedule,
trips_file_path=args.schedule_path,
vehicle_types_path=args.vehicle_types_path,
electrified_stations_path=args.electrified_stations_path,
cost_parameters_path=args.cost_parameters_path,
Expand All @@ -69,6 +72,7 @@ def add_trip_data_from_csv(self, file_path: Path) -> 'DataContainer':
trip_d[TEMPERATURE] = util.cast_float_or_none(trip.get(TEMPERATURE))
trip_d["distance"] = float(trip["distance"])
self.trip_data.append(trip_d)
util.save_input_file(file_path, self.args)
return self

def add_station_geo_data(self, data: dict) -> None:
Expand Down Expand Up @@ -162,6 +166,7 @@ def add_station_geo_data_from_csv(self, file_path: Path) -> 'DataContainer':
msg=f"Can't parse numeric data in line {line_num + 2} from file {file_path}.",
level=100)
raise
util.save_input_file(file_path, self.args)
return self

def add_level_of_loading_data(self, data: dict) -> 'DataContainer':
Expand All @@ -186,6 +191,7 @@ def add_level_of_loading_data_from_csv(self, file_path: Path) -> 'DataContainer'
index = "hour"
column = "level_of_loading"
level_of_loading_data_dict = util.get_dict_from_csv(column, file_path, index)
util.save_input_file(file_path, self.args)
self.add_level_of_loading_data(level_of_loading_data_dict)
return self

Expand All @@ -209,6 +215,7 @@ def add_temperature_data_from_csv(self, file_path: Path) -> 'DataContainer':
index = "hour"
column = "temperature"
temperature_data_dict = util.get_dict_from_csv(column, file_path, index)
util.save_input_file(file_path, self.args)
self.add_temperature_data(temperature_data_dict)
return self

Expand All @@ -231,6 +238,7 @@ def add_cost_parameters_from_json(self, file_path: Path) -> 'DataContainer':
:return: DataContainer containing cost parameters
"""
cost_parameters = self.get_json_from_file(file_path, "cost parameters")
util.save_input_file(file_path, self.args)
self.add_cost_parameters(cost_parameters)
return self

Expand All @@ -253,6 +261,7 @@ def add_stations_from_json(self, file_path: Path) -> 'DataContainer':
"""
stations = self.get_json_from_file(file_path, "electrified stations")
util.save_input_file(file_path, self.args)
self.add_stations(stations)
return self

Expand All @@ -274,6 +283,7 @@ def add_vehicle_types_from_json(self, file_path: Path):
:return: DataContainer containing vehicle types
"""
vehicle_types = self.get_json_from_file(file_path, "vehicle types")
util.save_input_file(file_path, self.args)
self.add_vehicle_types(vehicle_types)
return self

Expand Down Expand Up @@ -311,6 +321,7 @@ def add_consumption_data_from_vehicle_type_linked_files(self):
delim = util.get_csv_delim(mileage_path)
df = pd.read_csv(mileage_path, sep=delim)
self.add_consumption_data(mileage_path, df)
util.save_input_file(mileage_path, self.args)
return self

def add_consumption_data(self, data_name, df: pd.DataFrame) -> 'DataContainer':
Expand Down
Loading

0 comments on commit f15fae9

Please sign in to comment.