Skip to content

Commit

Permalink
new option create_trips_in_report
Browse files Browse the repository at this point in the history
  • Loading branch information
stefan.schirmeister committed Jun 20, 2024
1 parent 67f8810 commit 01bc068
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 3 deletions.
6 changes: 4 additions & 2 deletions data/examples/simba.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,21 @@ mode = ["sim", "report"]
##### Flags #####
### Activate optional functions ###
# Set flag for cost calculation: (default: false)
cost_calculation = true
cost_calculation = false
# Check rotation assumptions when building schedule? (default: false)
check_rotation_consistency = false
# Remove rotations from schedule that violate assumptions?
# Needs check_rotation_consistency to have an effect (default: false)
skip_inconsistent_rotations = false
# Show plots for users to view, only used in mode report (default: false)
show_plots = true
show_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
# null: deactivate function
rotation_filter_variable = null
# Write a new trips.csv during report mode to output directory? (default: false)
create_trips_in_report = false

##### Charging strategy #####
# Preferred charging type. Options: depb, oppb (default: depb)
Expand Down
37 changes: 37 additions & 0 deletions simba/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,39 @@ def generate_gc_overview(schedule, scenario, args):
*use_factors])


def generate_trips_timeseries_data(schedule):
"""
Build a trip data structure that can be saved to CSV.
This should be in the form of a valid trips.csv input file.
:param schedule: current schedule for the simulation
:type schedule: simba.Schedule
:return: trip data
:rtype: Iterable
"""
header = [
# identifier
"rotation_id", "line",
# stations
"departure_name", "departure_time", "arrival_name", "arrival_time",
# types
"vehicle_type", "charging_type",
# consumption (minimal)
"distance", "consumption"
# consumption (extended). Not strictly needed.
# "distance", "temperature", "height_diff", "level_of_loading", "mean_speed",
]
data = [header]
for rotation in schedule.rotations.values():
for trip in rotation.trips:
# get trip info from trip or trip.rotation (same name in Trip/Rotation as in CSV)
row = [vars(trip).get(k, vars(trip.rotation).get(k)) for k in header]
# special case rotation_id
row[0] = trip.rotation.id
data.append(row)
return data


def generate_plots(scenario, args):
""" Save plots as png and pdf.
Expand Down Expand Up @@ -251,6 +284,10 @@ def generate(schedule, scenario, args):
csv_writer.writeheader()
csv_writer.writerows(rotation_infos)

if vars(args).get('create_trips_in_report', False):
file_path = args.results_directory / "trips.csv"
write_csv(generate_trips_timeseries_data(schedule), file_path)

# summary of used vehicle types and all costs
if args.cost_calculation:
file_path = args.results_directory / "summary_vehicles_costs.csv"
Expand Down
2 changes: 1 addition & 1 deletion simba/trip.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def __init__(self, rotation, departure_time, departure_name,
mean_speed = kwargs.get("mean_speed", (self.distance / 1000) /
max(1 / 60, ((self.arrival_time - self.departure_time) / timedelta(
hours=1))))
self.mean_speed = mean_speed
self.mean_speed = float(mean_speed)

# Attention: Circular reference!
# While a rotation carries a references to this trip, this trip
Expand Down
2 changes: 2 additions & 0 deletions simba/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,8 @@ def get_args():
parser.add_argument('--propagate-mode-errors', default=False,
help='Re-raise errors instead of continuing during simulation modes')
parser.add_argument('--create-scenario-file', help='Write scenario.json to file')
parser.add_argument('--create-trips-in-report', action='store_true',
help='Write a trips.csv during report mode')
parser.add_argument('--rotation-filter-variable', default=None,
choices=[None, 'include', 'exclude'],
help='set mode for filtering schedule rotations')
Expand Down
1 change: 1 addition & 0 deletions tests/test_schedule.py
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,7 @@ def test_peak_load_window(self):

sys.argv = ["foo", "--config", str(example_root / "simba.cfg")]
args = util.get_args()
args.cost_calculation = True # needed for timeseries, but default is false
for station in generated_schedule.stations.values():
station["gc_power"] = 1000
station.pop("peak_load_window_power", None)
Expand Down
21 changes: 21 additions & 0 deletions tests/test_simulate.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,27 @@ def test_empty_report(self, tmp_path):
warnings.simplefilter("ignore")
simulate(Namespace(**values))

def test_create_trips_in_report(self, tmp_path):
# create_trips_in_report option: must generate valid input trips.csv
values = self.DEFAULT_VALUES.copy()
values.update({
"mode": ["report"],
"desired_soc_deps": 0,
"ALLOW_NEGATIVE_SOC": True,
"cost_calculation": False,
"output_directory": tmp_path,
"show_plots": False,
"create_trips_in_report": True,
})
# simulate base scenario, report generates new trips.csv in (tmp) output
with warnings.catch_warnings():
warnings.simplefilter("ignore")
simulate(Namespace(**values))
# new simulation with generated trips.csv
values = self.DEFAULT_VALUES.copy()
values["input_schedule"] = tmp_path / "report_1/trips.csv"
simulate(Namespace(**(values)))

def test_mode_recombination(self):
values = self.DEFAULT_VALUES.copy()
values["mode"] = "recombination"
Expand Down

0 comments on commit 01bc068

Please sign in to comment.