Skip to content

Commit

Permalink
Make lol and temperatures optional again. make changed config paramet…
Browse files Browse the repository at this point in the history
…er names backwards compatible

Simulation can run without temperatures and lol if vehicle_types have constant mileage. vehicle types with mileage look up will fail late. Arguments expanded with deprecated values which replace current values. Warning for deprecation is given. Station Height data lookup will give errors in case station is missing from station_data. in other cases a single warning is given if no station data is provided
  • Loading branch information
PaulScheerRLI committed Sep 19, 2024
1 parent 68e6ac7 commit a70923a
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 10 deletions.
28 changes: 18 additions & 10 deletions simba/schedule.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,29 +103,38 @@ def from_datacontainer(cls, data: DataContainer, args):
# Add geo data to schedule
schedule.station_data = data.station_geo_data

if not schedule.station_data:
logging.warning(
"No station data found for schedule. Height difference for all trips set to 0")

# Add consumption calculator to trip class
schedule.consumption_calculator = Consumption.create_from_data_container(data)

for trip in data.trip_data:
# De-link DataContainer and Schedule instances
trip = {key: data for key, data in trip.items()}
rotation_id = trip['rotation_id']

# Get height difference from station_data
trip["height_difference"] = schedule.get_height_difference(
trip["departure_name"], trip["arrival_name"])

if trip["level_of_loading"] is None:
assert len(data.level_of_loading_data) == 24, "Need 24 entries in level of loading"
trip["level_of_loading"] = util.get_mean_from_hourly_dict(
data.level_of_loading_data, trip["departure_time"], trip["arrival_time"])
if data.level_of_loading_data:
assert len(data.level_of_loading_data) == 24, \
"Need 24 entries in level of loading"
trip["level_of_loading"] = util.get_mean_from_hourly_dict(
data.level_of_loading_data, trip["departure_time"], trip["arrival_time"])
else:
if not 0 <= trip["level_of_loading"] <= 1:
logging.warning("Level of loading is out of range [0,1] and will be clipped.")
trip["level_of_loading"] = min(1, max(0, trip["level_of_loading"]))

if trip["temperature"] is None:
assert len(data.temperature_data) == 24, "Need 24 entries in temperature data"
trip["temperature"] = util.get_mean_from_hourly_dict(
data.temperature_data, trip["departure_time"], trip["arrival_time"])
if data.temperature_data:
assert len(data.temperature_data) == 24, "Need 24 entries in temperature data"
trip["temperature"] = util.get_mean_from_hourly_dict(
data.temperature_data, trip["departure_time"], trip["arrival_time"])

if rotation_id not in schedule.rotations.keys():
schedule.rotations.update({
Expand Down Expand Up @@ -727,7 +736,7 @@ def get_height_difference(self, departure_name, arrival_name):
:return: Height difference. Defaults to 0 if height data is not found.
:rtype: float
"""
if isinstance(self.station_data, dict):
if isinstance(self.station_data, dict) and self.station_data:
station_name = departure_name
try:
start_height = self.station_data[station_name]["elevation"]
Expand All @@ -736,9 +745,8 @@ def get_height_difference(self, departure_name, arrival_name):
return end_height - start_height
except KeyError:
logging.error(
f"No elevation data found for {station_name}. Height difference set to 0")
else:
logging.error("No station data found for schedule. Height difference set to 0")
f"No elevation data found for {station_name} in station_data. "
"Height difference set to 0")
return 0

def get_negative_rotations(self, scenario):
Expand Down
34 changes: 34 additions & 0 deletions simba/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,30 @@ def get_buffer_time(trip, default=0):
return buffer_time


def replace_deprecated_arguments(args):
if args.electrified_stations is not None:
assert args.electrified_stations_path is None
logging.warning("The parameter 'electrified_stations' is deprecated. "
"Use 'electrified_stations_path 'instead.")
args.electrified_stations_path = args.electrified_stations
del args.electrified_stations

if args.vehicle_types is not None:
assert args.vehicle_types_path is None
logging.warning("The parameter 'vehicle_types' is deprecated. "
"Use 'vehicle_types_path 'instead.")
args.vehicle_types_path = args.vehicle_types
del args.vehicle_types

if args.cost_parameters_file is not None:
assert args.cost_parameter_path is None
logging.warning("The parameter 'cost_parameter_file' is deprecated. "
"Use 'cost_parameter_path 'instead.")
args.cost_parameter_path = args.cost_parameters_file
del args.cost_parameters_file
return args


def mutate_args_for_spiceev(args):
# arguments relevant to SpiceEV, setting automatically to reduce clutter in config
args.margin = 1
Expand All @@ -357,6 +381,9 @@ def get_args():
# If a config is provided, the config will overwrite previously parsed arguments
set_options_from_config(args, check=parser, verbose=False)

# Check if deprecated arguments were given and change them accordingly
args = replace_deprecated_arguments(args)

# rename special options
args.timing = args.eta

Expand Down Expand Up @@ -528,6 +555,13 @@ def get_parser():
parser.add_argument('--time-windows', metavar='FILE',
help='use peak load windows to force lower power '
'during times of high grid load')
# Deprecated options for downwards compatibility
parser.add_argument('--electrified-stations', default=None,
help='Deprecated use "electrified-stations-path" instead')
parser.add_argument('--vehicle-types', default=None,
help='Deprecated use "vehicle-types-path" instead')
parser.add_argument('--cost-parameters-file', default=None,
help='Deprecated use "cost-parameters-path" instead')

parser.add_argument('--config', help='Use config file to set arguments')
return parser
40 changes: 40 additions & 0 deletions tests/test_schedule.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,46 @@ def basic_run(self):

class TestSchedule(BasicSchedule):

def test_optional_timeseries(self):
# Test if simulation runs if level of loading and temperature timeseries is not given
sys.argv = ["foo", "--config", str(example_root / "simba.cfg")]
args = util.get_args()
data_container = DataContainer().fill_with_args(args)
vehicle_mileage_path = None
found = False
for vt in data_container.vehicle_types_data.values():
for ct in vt.values():
if isinstance(ct["mileage"], str):
vehicle_mileage_path = ct["mileage"]
found = True
break
if found:
break

sched, args = pre_simulation(args, data_container)

# Make sure at least a single used vehicle type has mileage lookup.
some_used_vehicle_type = next(iter(sched.rotations.values())).vehicle_type
data_container.vehicle_types_data[some_used_vehicle_type][
"oppb"]["mileage"] = vehicle_mileage_path
data_container.vehicle_types_data[some_used_vehicle_type][
"depb"]["mileage"] = vehicle_mileage_path

# Delete the lol and temp data sources -> pre-simulation should fail,
# since consumption cannot be calculated
data_container.level_of_loading_data = {}
data_container.temperature_data = {}
for trip in data_container.trip_data:
print(trip)
with pytest.raises(Exception):
sched, args = pre_simulation(args, data_container)

# if all vehicle types have constant consumption, pre-simulation should work
for vt in data_container.vehicle_types_data.values():
for ct in vt.values():
ct["mileage"] = 1
_, _ = pre_simulation(args, data_container)

def test_timestep(self):
# Get the parser from util. This way the test is directly coupled to the parser arguments
sys.argv = ["foo", "--config", str(example_root / "simba.cfg")]
Expand Down
2 changes: 2 additions & 0 deletions tests/test_simulate.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ def get_args(self):
parser.set_defaults(**self.NON_DEFAULT_VALUES)
# get all args with default values
args, _ = parser.parse_known_args()
args = util.replace_deprecated_arguments(args)

return args

def test_basic(self):
Expand Down

0 comments on commit a70923a

Please sign in to comment.