Source code for pybtls.traffic.lfc

"""
The methods and classes that are not defined in Python are defined in C++ py_main.cpp. 
"""

from ..lib.BTLS import _LaneFlowComposition
from typing import Literal

__all__ = ["LaneFlowComposition"]


[docs] class LaneFlowComposition: def __init__( self, lane_index: int, lane_dir: Literal[1, 2], no_block: int = 24, block_size: int = 3600, tag: str = "Now", ): """ The LaneFlowComposition instance stores the data for creating a CLaneFlowComposition instance in C++. \n The hourly flow, speed, and truck composition data for a lane. Parameters ---------- lane_index : int\n The index of the lane. 1-based global index. lane_dir : Literal[1,2]\n The direction of the lane.\n 1 - vehicles drive from left to right.\n 2 - vehicles drive from right to left.\n Must be in the same coordinate system used when defining the bridge. no_block : int, optional\n The number of blocks in a day. The default is 24. block_size : int, optional\n The size of a block in seconds. The default is 3600. tag : str, optional\n To tag the moment of the lane flow composition. The default is "Now". """ self._tag = tag self._lane_index = lane_index # at here it is still 1-based self._lane_dir = lane_dir self._no_block = no_block self._block_size = block_size self._hourly_truck_flow = [1] * no_block # in veh/h self._hourly_car_percentage = [0.0] * no_block # in percent self._hourly_speed_mean = [248] * no_block # in dm/s self._hourly_speed_std = [10] * no_block # in dm/s self._hourly_truck_composition = [ [100.0] for _ in range(no_block) ] # in percent self._flow_assigned = False # garage, grave, nominal need hourly flow self._speed_assigned = False # NHM, freeflow need hourly speed self._truck_composition_assigned = False # grave need hourly truck percentage def __getstate__(self): attribute_dict = {} attribute_dict["tag"] = self._tag attribute_dict["lane_index"] = self._lane_index attribute_dict["lane_dir"] = self._lane_dir attribute_dict["no_block"] = self._no_block attribute_dict["block_size"] = self._block_size attribute_dict["hourly_truck_flow"] = self._hourly_truck_flow attribute_dict["hourly_car_percentage"] = self._hourly_car_percentage attribute_dict["hourly_speed_mean"] = self._hourly_speed_mean attribute_dict["hourly_speed_std"] = self._hourly_speed_std attribute_dict["hourly_truck_composition"] = self._hourly_truck_composition attribute_dict["flow_assigned"] = self._flow_assigned attribute_dict["speed_assigned"] = self._speed_assigned attribute_dict["truck_composition_assigned"] = self._truck_composition_assigned return attribute_dict def __setstate__(self, attribute_dict): self._tag = attribute_dict["tag"] self._lane_index = attribute_dict["lane_index"] self._lane_dir = attribute_dict["lane_dir"] self._no_block = attribute_dict["no_block"] self._block_size = attribute_dict["block_size"] self._hourly_truck_flow = attribute_dict["hourly_truck_flow"] self._hourly_car_percentage = attribute_dict["hourly_car_percentage"] self._hourly_speed_mean = attribute_dict["hourly_speed_mean"] self._hourly_speed_std = attribute_dict["hourly_speed_std"] self._hourly_truck_composition = attribute_dict["hourly_truck_composition"] self._flow_assigned = attribute_dict["flow_assigned"] self._speed_assigned = attribute_dict["speed_assigned"] self._truck_composition_assigned = attribute_dict["truck_composition_assigned"] @property def tag(self) -> str: return self._tag @property def lane_index(self) -> int: return self._lane_index @property def lane_dir(self) -> int: return self._lane_dir @property def flow_assigned(self) -> bool: return self._flow_assigned @property def speed_assigned(self) -> bool: return self._speed_assigned @property def truck_composition_assigned(self) -> bool: return self._truck_composition_assigned
[docs] def assign_lane_data(self, **kwargs) -> None: """ Assign the required data to the lane for traffic generation. Keyword Arguments ----------------- hourly_truck_flow : list[float]\n The hourly truck flow data in veh/h. hourly_car_flow : list[float]\n The hourly car flow data in veh/h. hourly_car_percentage : list[float]\n The hourly car percentage data in percent. hourly_speed_mean : list[float]\n The hourly mean speed data in dm/s. hourly_speed_std : list[float]\n The hourly standard deviation of speed data in dm/s. hourly_truck_composition : list[list[float]]\n The hourly truck composition data in percent. The list should only consist of four truck percentages. Returns ------- None. """ if ( kwargs.get("hourly_truck_flow") is not None and kwargs.get("hourly_car_flow") is not None ): self._set_hourly_flow1( kwargs.get("hourly_truck_flow"), kwargs.get("hourly_car_flow") ) elif ( kwargs.get("hourly_truck_flow") is not None and kwargs.get("hourly_car_percentage") is not None ): self._set_hourly_flow2( kwargs.get("hourly_truck_flow"), kwargs.get("hourly_car_percentage") ) if ( kwargs.get("hourly_speed_mean") is not None and kwargs.get("hourly_speed_std") is not None ): self._set_hourly_speed( kwargs.get("hourly_speed_mean"), kwargs.get("hourly_speed_std") ) if kwargs.get("hourly_truck_composition") is not None: self._set_hourly_truck_composition(kwargs.get("hourly_truck_composition"))
def _set_hourly_flow1(self, hourly_truck_flow, hourly_car_flow): if ( len(hourly_truck_flow) != self._no_block or len(hourly_car_flow) != self._no_block ): raise ValueError("Length of hourly flow data does not match.") self._hourly_truck_flow = hourly_truck_flow for i in range(self._no_block): self._hourly_car_percentage[i] = ( hourly_car_flow[i] / (hourly_car_flow[i] + hourly_truck_flow[i]) * 100 ) self._flow_assigned = True def _set_hourly_flow2(self, hourly_truck_flow, hourly_car_percentage): if ( len(hourly_truck_flow) != self._no_block or len(hourly_car_percentage) != self._no_block ): raise ValueError("Length of hourly flow data does not match.") self._hourly_truck_flow = hourly_truck_flow self._hourly_car_percentage = hourly_car_percentage self._flow_assigned = True def _set_hourly_speed(self, hourly_speed_mean, hourly_speed_std): if ( len(hourly_speed_mean) != self._no_block or len(hourly_speed_std) != self._no_block ): raise ValueError("Length of hourly speed data does not match.") self._hourly_speed_mean = hourly_speed_mean self._hourly_speed_std = hourly_speed_std self._speed_assigned = True def _set_hourly_truck_composition( self, hourly_truck_composition: list[list[float]] ): if not isinstance(hourly_truck_composition[0], list): raise TypeError("Hourly Truck composition data should be a list of lists.") if len(hourly_truck_composition) != self._no_block: raise ValueError("Length of hourly Truck composition data does not match.") if not all(len(sublist) == 4 for sublist in hourly_truck_composition): raise ValueError( "The hourly truck composition data should only consist of four truck percentages." ) self._hourly_truck_composition = hourly_truck_composition self._truck_composition_assigned = True def _get_LFC(self): """ Get a CLaneFlowComposition instance (lane flow composition). """ lfc = _LaneFlowComposition( self._lane_index - 1, self._lane_dir, self._block_size ) # in C++ BTLS, lane_index is 0-based when create CLFC in CReadLaneData for i in range(self._no_block): data_vector = [] data_vector.append(float(i)) data_vector.append(self._hourly_truck_flow[i]) data_vector.append(self._hourly_speed_mean[i]) data_vector.append(self._hourly_speed_std[i]) data_vector.append(self._hourly_car_percentage[i]) for j in range(len(self._hourly_truck_composition[i])): data_vector.append(self._hourly_truck_composition[i][j]) lfc.addBlockData(data_vector) # C++ function lfc.completeData() # C++ function return lfc